文档
- 1: 参考
- 1.1: 语言规范
- 1.1.1: 简介
- 1.1.2: 标记法
- 1.1.3: 源代码表示
- 1.1.4: 词汇元素
- 1.1.5: 常量
- 1.1.6: 变量
- 1.1.7: 类型
- 1.1.8: 类型和值的属性
- 1.1.9: 块
- 1.1.10: 声明和作用域
- 1.1.11: 表达式
- 1.1.12: 语句
- 1.1.13: 内置函数
- 1.1.14: 包
- 1.1.15: 程序初始化和执行
- 1.1.16: 错误
- 1.1.17: 运行时恐慌
- 1.1.18: 系统考虑
- 1.2: Go内存模型
- 1.3: 命令文档
- 1.3.1: 全部命令
- 1.3.2: internal
- 1.3.2.1: brower
- 1.3.2.2: buildid
- 1.3.2.3: codesign
- 1.3.2.4: dwarf
- 1.3.2.5: edit
- 1.3.2.6: gcprog
- 1.3.2.7: goobj
- 1.3.2.8: notsha256
- 1.3.2.9: obj
- 1.3.2.10: obj_arm
- 1.3.2.11: obj_arm64
- 1.3.2.12: obj_loong62
- 1.3.2.13: obj_mips
- 1.3.2.14: obj_ppc64
- 1.3.2.15: obj_riscv
- 1.3.2.16: obj_s390x
- 1.3.2.17: obj_wasm
- 1.3.2.18: obj_x86
- 1.3.2.19: objabi
- 1.3.2.20: objfile
- 1.3.2.21: osinfo
- 1.3.2.22: pkgpath
- 1.3.2.23: quoted
- 1.3.2.24: src
- 1.3.2.25: sys
- 1.3.2.26: test2json
- 1.3.2.27: traceviewer
- 1.3.2.28: archive
- 1.3.2.29: bio
- 1.3.3: addr2line
- 1.3.4: api
- 1.3.5: asm
- 1.3.6: buildid
- 1.3.7: cgo
- 1.3.8: compile
- 1.3.9: cover
- 1.3.10: dist
- 1.3.11: doc
- 1.3.12: fix
- 1.3.13: go
- 1.3.14: go 命令首页表格
- 1.3.15: go1
- 1.3.16: godoc
- 1.3.17: gofmt
- 1.3.18: gofmt 2
- 1.3.19: link
- 1.3.20: nm
- 1.3.21: objabi
- 1.3.22: objdump
- 1.3.23: pack
- 1.3.24: pprof
- 1.3.25: test2json
- 1.3.26: trace
- 1.3.27: vet
- 1.4: Go Modules Reference
- 1.4.1: 简介
- 1.4.2: 模块、包和版本
- 1.4.3: go.mod 文件
- 1.4.4: 最小版本选择 (MVS)
- 1.4.5: 模块图的修剪
- 1.4.6: 工作区
- 1.4.7: 与非模块存储库的兼容性
- 1.4.8: 具有模块感知的命令
- 1.4.9: 模块代理
- 1.4.10: 版本控制系统
- 1.4.11: 模块zip文件
- 1.4.12: 私有模块
- 1.4.13: 模块缓存
- 1.4.14: 验证模块
- 1.4.15: 环境变量
- 1.4.16: 词汇表
- 1.5: go.mod 文件参考
- 1.6: Contribution Guide
- 1.7: Release History
- 2: 标准库
- 2.1: archive
- 2.2: compress
- 2.3: container
- 2.4: crypto
- 2.4.1: aes
- 2.4.2: cipher
- 2.4.3: crypto
- 2.4.4: des
- 2.4.5: dsa
- 2.4.6: ecdh
- 2.4.7: ecdsa
- 2.4.8: ed25519
- 2.4.9: elliptic
- 2.4.10: hmac
- 2.4.11: md5
- 2.4.12: rand
- 2.4.13: rc4
- 2.4.14: rsa
- 2.4.15: sha1
- 2.4.16: sha256
- 2.4.17: sha512
- 2.4.18: subtle
- 2.4.19: tls
- 2.4.20: x509
- 2.4.21: x509/pkix
- 2.5: database
- 2.5.1: sql
- 2.5.2: sql/driver
- 2.6: debug
- 2.7: encoding
- 2.7.1: ascii85
- 2.7.2: asn1
- 2.7.3: base32
- 2.7.4: base64
- 2.7.5: binary
- 2.7.6: csv
- 2.7.7: encoding
- 2.7.8: gob
- 2.7.9: hex
- 2.7.10: json
- 2.7.11: pem
- 2.7.12: xml
- 2.8: go
- 2.8.1: ast
- 2.8.2: build
- 2.8.3: constant
- 2.8.4: contraint
- 2.8.5: doc
- 2.8.6: doc/comment
- 2.8.7: format
- 2.8.8: importer
- 2.8.9: parser
- 2.8.10: printer
- 2.8.11: scanner
- 2.8.12: token
- 2.8.13: types
- 2.9: hash
- 2.10: html
- 2.11: image
- 2.12: index
- 2.12.1: suffixarray
- 2.13: internal
- 2.13.1:
- 2.13.2:
- 2.13.3:
- 2.13.4:
- 2.13.5:
- 2.13.6:
- 2.13.7:
- 2.13.8:
- 2.13.9:
- 2.13.10:
- 2.13.11:
- 2.13.12:
- 2.13.13:
- 2.13.14:
- 2.13.15:
- 2.13.16:
- 2.13.17:
- 2.13.18:
- 2.13.19:
- 2.13.20:
- 2.13.21:
- 2.13.22:
- 2.13.23:
- 2.13.24:
- 2.13.25:
- 2.13.26:
- 2.13.27:
- 2.13.28:
- 2.13.29:
- 2.13.30:
- 2.13.31:
- 2.13.32:
- 2.13.33:
- 2.13.34:
- 2.13.35:
- 2.13.36:
- 2.13.37:
- 2.13.38:
- 2.13.39:
- 2.13.40:
- 2.13.41:
- 2.13.42:
- 2.13.43:
- 2.13.44:
- 2.13.45:
- 2.13.46:
- 2.13.47:
- 2.13.48:
- 2.13.49:
- 2.13.50:
- 2.13.51:
- 2.13.52:
- 2.13.53:
- 2.13.54:
- 2.13.55:
- 2.13.56:
- 2.13.57:
- 2.13.58:
- 2.13.59:
- 2.14: io
- 2.15: log
- 2.15.1: log
- 2.15.2: logAnalysis
- 2.15.3: syslog
- 2.16: math
- 2.17: mime
- 2.17.1: mime
- 2.17.2: multipart
- 2.17.3: quotedprintable
- 2.18: net
- 2.18.1: fcgi
- 2.18.2: http
- 2.18.3: http/cli
- 2.18.4: http/cookiejar
- 2.18.5: http/httptest
- 2.18.6: http/httptrace
- 2.18.7: http/httputil
- 2.18.8: mail
- 2.18.9: net
- 2.18.10: netip
- 2.18.11: pprof
- 2.18.12: rpc
- 2.18.13: rpc/jsonrpc
- 2.18.14: smtp
- 2.18.15: textproto
- 2.18.16: url
- 2.19: os
- 2.20: path
- 2.21: regexp
- 2.22: runtime
- 2.22.1: cgo
- 2.22.2: coverage
- 2.22.3: debug
- 2.22.4: metrics
- 2.22.5: pprof
- 2.22.6: race
- 2.22.7: runtime
- 2.22.8: trace
- 2.23: sync
- 2.24: syscall
- 2.25: testing
- 2.26: text
- 2.26.1: scanner
- 2.26.2: tabwriter
- 2.26.3: template
- 2.26.4: template/parse
- 2.27: time
- 2.28: bufio
- 2.29: builtin
- 2.30: bytes
- 2.31: context
- 2.32: embed
- 2.33: error
- 2.34: expvar
- 2.35: flag
- 2.36: fmt
- 2.37: plugin
- 2.38: reflect
- 2.39: sort
- 2.40: strconv
- 2.41: strings
- 2.42: unicode
- 2.43: unsafe
- 3: 使用和理解Go
- 3.1: Effective Go
- 3.2: Go Fuzzing
- 3.3: Go垃圾收集器指南
- 3.4: 开发模块
- 3.5: 管理依赖项
- 3.6: 编辑器插件和IDEs
- 3.7: 访问数据库
- 3.7.1: 访问关系型数据库
- 3.7.2: 打开一个数据库句柄
- 3.7.3: 执行不返回数据的SQL语句
- 3.7.4: 查询数据
- 3.7.5: 使用预处理语句
- 3.7.6: 执行事务
- 3.7.7: 取消正在进行的操作
- 3.7.8: 管理连接
- 3.7.9: 避免SQL注入风险
- 3.8: 诊断
- 4: Go Tour
- 4.1: 欢迎
- 4.2: 基础
- 4.2.1: Packages, variables, and functions
- 4.2.2: Flow control statements: for, if, else, switch and defer
- 4.2.3: More types: structs, slices, and maps
- 4.3: 方法和接口
- 4.4: 泛型
- 4.5: 并发
1 - 参考
1.1 - 语言规范
1.1.1 - 简介
The Go Programming Language Specification
Version of June 29, 2022
Introduction 简介
这是Go编程语言的参考手册。不带泛型的 Go1.18 之前的版本可以在这里找到。更多信息和其他文档,请参见 golang.org。
Go是一种通用语言,设计时考虑到了系统编程。它是强类型和垃圾收集的,并且明确支持并发编程。程序是由包构成的,包的属性允许对依赖项进行有效的管理。
语法紧凑且易于解析,允许使用集成开发环境等自动工具进行轻松的分析。
1.1.2 - 标记法
Notation 标记法
(标记法的)语法是用 Extended Backus-Naur Form (EBNF) 的一个变体来指定的。
Syntax = { Production } .
Production = production_name "=" [ Expression ] "." .
Expression = Term { "|" Term } .
Term = Factor { Factor } .
Factor = production_name | token [ "…" token ] | Group | Option | Repetition .
Group = "(" Expression ")" .
Option = "[" Expression "]" .
Repetition = "{" Expression "}" .
Productions are expressions constructed from terms and the following operators, in increasing precedence:
产生式是由术语和以下运算符构建的表达式,其优先级越来越高。
| alternation
() grouping
[] option (0 or 1 times)
{} repetition (0 to n times)
小写的产生式名称用于标识词法(终端)标记。非终端则使用CamelCase。词法标记用双引号""或反引号``包裹起来。
a ... b的形式表示从a到b的一组字符作为备选项。在规范的其他地方也使用水平省略号...来非正式地表示各种枚举或没有进一步指定的代码片段。字符…(相对于三个字符...而言)不是Go语言的标记。
1.1.3 - 源代码表示
Source code representation 源代码表示
源代码是以 UTF-8编码的Unicode文本。该文本未被规范化,因此单个重音码点与由重音和字母组合而成的相同字符是不同的;这些被视为两个码点。为了简单起见,本文将使用非限定术语字符来指代源文本中的Unicode码点。
每个码点都是不同的;例如,大写字母和小写字母是不同的字符。
实现限制:为了与其他工具兼容,编译器可能不允许源文本中出现NUL字符(U+0000)。
实现限制:为了与其他工具兼容,编译器可以忽略UTF-8编码的字节顺序标记(U+FEFF),如果它是源文本中的第一个Unicode码点。字节顺序标记可能在源代码的其他任何地方被禁用。
Characters 字符
以下术语用于表示特定的Unicode字符类别:
newline = /* the Unicode code point U+000A */ .
unicode_char = /* an arbitrary Unicode code point except newline */ .
unicode_letter = /* a Unicode code point categorized as "Letter" */ .
unicode_digit = /* a Unicode code point categorized as "Number, decimal digit" */ .
在 The Unicode Standard 8.0中,第4.5节 “General Category “定义了一组字符类别。Go将字母类别Lu、Ll、Lt、Lm或Lo中的所有字符视为Unicode字母,将数字类别Nd中的字符视为Unicode数字。
Letters and digits 字母和数字
下划线字符_(U+005F)被视为小写字母。
letter = unicode_letter | "_" .
decimal_digit = "0" … "9" .
binary_digit = "0" | "1" .
octal_digit = "0" … "7" .
hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
1.1.4 - 词汇元素
Lexical elements 词汇元素
Comments 注释
注释服务于程序文档,有两种形式:
- 行注释以字符序列
//开始,并在行尾结束。 - 通用注释以字符序列
/*开始,并以随后的第一个字符序列*/结束。
注释不能从rune或string literal开始,也不能从注释内部开始。一个不包含换行符的通用注释就像一个空格。任何其他的注释就像一个换行符。
Tokens
tokens 构成了Go语言的词汇表。有四个类别:标识符、关键字、操作符和标点符号以及字面量(literals)。由空格(U+0020)、水平制表符(U+0009)、回车符(U+000D)和换行符(U+000A)组成的空白空间被忽略,除非它分隔本来会合并成单个标记的标记。此外,换行或文件结束可能会触发插入分号semicolon 。当把输入分解为 tokens 时,下一个 token 是形成有效 token 的最长的字符序列。
Semicolons 分号
正式语法(formal syntax)在许多结果(productions)中使用分号";“作为终止符。Go程序可以通过以下两条规则省略大部分的分号:
a. 当输入被分解成 tokens 时,分号会自动插入标记流后,如果某行的最后一个 token 是:
-
一个标识符(identifier)
-
break、continue、fallthrough、return中的任意一个关键字 -
++、--、)、]、}中的任意一个操作符或标点符号
b. 为了允许复杂的语句占用一行,在结尾的”)“或”}“之前可以省略分号。
为了响应惯用法(idiomatic use),本文档中的代码示例使用这些规则省略分号。
Identifiers 标识符
标识符命名程序实体,如变量和类型。标识符是一个或多个字母和数字的序列。标识符中的第一个字符必须是字母。
identifier = letter { letter | unicode_digit } .
a
_x9
ThisVariableIsExported
αβ
一些标识符是预先声明的(predeclared)。
Keywords 关键字
以下关键词被作为保留,不能作为标识符使用:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
Operators and punctuation 操作符和标点符号
以下字符序列代表运算符(operators)(包括赋值运算符(assignment operators))和标点符号:
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^= ~
Integer literals 整数字面量
整数字面量是代表一个整数常量的数字序列。可选的前缀用于设置非十进制的基数。二进制为0b或0B,八进制为0、0o或0O,十六进制为0x或0X。单一的0被认为是十进制的0。在十六进制字面量中,字母a到f和A到F代表数值10到15。
为了便于阅读,下划线字符_可以出现在基数前缀之后或连续的数字之间。这种下划线不会改变字面的值。(只有从 go 1.几的版本及以上版本才可以使用)
int_lit = decimal_lit | binary_lit | octal_lit | hex_lit .
decimal_lit = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] .
binary_lit = "0" ( "b" | "B" ) [ "_" ] binary_digits .
octal_lit = "0" [ "o" | "O" ] [ "_" ] octal_digits .
hex_lit = "0" ( "x" | "X" ) [ "_" ] hex_digits .
decimal_digits = decimal_digit { [ "_" ] decimal_digit } .
binary_digits = binary_digit { [ "_" ] binary_digit } .
octal_digits = octal_digit { [ "_" ] octal_digit } .
hex_digits = hex_digit { [ "_" ] hex_digit } .
42
4_2
0600
0_600
0o600
0O600 // second character is capital letter 'O' => 第二个字符是字母 'O'
0xBadFace
0xBad_Face
0x_67_7a_2f_cc_40_c6
170141183460469231731687303715884105727
170_141183_460469_231731_687303_715884_105727
_42 // an identifier, not an integer literal => 标识符,非整数字面量42
42_ // invalid: _ must separate successive digits
//=> 无效的:_ 必须分隔连续的数字 (但0x_1FA或 0X_1FA 等字面量却是有效的)
4__2 // invalid: only one _ at a time
//=> 无效的:每次只能使用一个 _(但0x_1FA或 0X_1FA 等字面量却是有效的)
0_xBadFace // invalid: _ must separate successive digits
//=> 无效的:_ 必须分隔连续的数字(但0x_1FA或 0X_1FA 等字面量却是有效的)
Floating-point literals 浮点数字面量
浮点数字面量是浮点常量的十进制或十六进制表示。
十进制浮点数字面量由整数部分(integer part)(十进制数字)、小数点( a radix point)、小数部分(fractional part )(十进制数字)和指数部分(exponent part )(e或E后面有可选的符号和十进制数字)组成。整数部分或小数部分中的一个可以省略;小数点或指数部分中的一个可以省略。指数值 exp 将尾数(mantissa )(整数和小数部分)按$10^{exp}$ 进行缩放。
十六进制浮点数字面量由0x或0X前缀(prefix)、整数部分(integer part)(十六进制数字)、小数点( a radix point)、小数部分(fractional part )(十六进制数字)和指数部分(exponent part )(p或P后面有可选的符号和十进制数字)组成。整数部分或小数部分中的一个可以省略;小数点也可以省略,但指数部分是必须要存在的。(这个语法与IEEE 754-2008 §5.12.3中给出的语法一致。) 指数值exp将尾数(mantissa )(整数和小数部分)按$2^{exp}$ 进行缩放。
为了便于阅读,一个下划线字符_可以出现在基数前缀之后或连续的数字之间;这样的下划线不会改变字面量的值。(只有从 go 1.几的版本及以上版本才可以使用)
float_lit = decimal_float_lit | hex_float_lit .
decimal_float_lit = decimal_digits "." [ decimal_digits ] [ decimal_exponent ] |
decimal_digits decimal_exponent |
"." decimal_digits [ decimal_exponent ] .
decimal_exponent = ( "e" | "E" ) [ "+" | "-" ] decimal_digits .
hex_float_lit = "0" ( "x" | "X" ) hex_mantissa hex_exponent .
hex_mantissa = [ "_" ] hex_digits "." [ hex_digits ] |
[ "_" ] hex_digits |
"." hex_digits .
hex_exponent = ( "p" | "P" ) [ "+" | "-" ] decimal_digits .
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5. // == 15.0 <= 省略小数部分
0.15e+0_2 // == 15.0 <= 这里有一个可选符号 +
0x1p-2 // == 0.25 <= 这里有一个可选符号 -
0x2.p10 // == 2048.0
0x1.Fp+0 // == 1.9375 <= 这里有一个可选符号 +
0X.8p-0 // == 0.5 <= 这里有一个可选符号 -
0X_1FFFP-16 // == 0.1249847412109375
0x15e-2 // == 0x15e - 2 (integer subtraction) 整数减法
//<= 相当于 ( 0x15e) - 2 = 348。
//注意这里的 e 是 十六进制表示法中的 e (表示十进制 14),
//而不是十进制浮点数字面量中的指数部分前面的 e
0x.p1 // invalid: mantissa has no digits
//=> 无效的: 尾数没有数字
1p-2 // invalid: p exponent requires hexadecimal mantissa
//=> 无效的:p 指数需要十六进制尾数
0x1.5e-2 // invalid: hexadecimal mantissa requires p exponent
//=> 无效的:十六进制尾数需要 p 指数
1_.5 // invalid: _ must separate successive digits
//=> 无效的:十六进制尾数需要 p 指数
1._5 // invalid: _ must separate successive digits
//=> 无效的:十六进制尾数需要 p 指数
1.5_e1 // invalid: _ must separate successive digits
//=> 无效的:十六进制尾数需要 p 指数
1.5e_1 // invalid: _ must separate successive digits
//=> 无效的:十六进制尾数需要 p 指数
1.5e1_ // invalid: _ must separate successive digits
//=> 无效的:十六进制尾数需要 p 指数
Imaginary literals 虚数字面量
虚数字面量表示一个复数常量的虚数部分。它由一个整数字面量或浮点数的字面量和小写字母i组成,虚数字面量的值是各个整数或浮点数字面量的值乘以虚数单位i。
imaginary_lit = (decimal_digits | int_lit | float_lit) "i" .
为了向后兼容,虚数字面量的整数部分完全由十进制数字(可能还有下划线)组成,被认为是一个十进制整数,即使它以前导0开始。
0i
0123i // == 123i for backward-compatibility
0o123i // == 0o123 * 1i == 83i
0xabci // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i // == 0x1p-2 * 1i == 0.25i
Rune literals 符文字面量
符文字面量表示一个符文常量,一个识别Unicode码点的整数值。一个符文字面量表示为一个或多个字符,用单引号包裹起来,如'x'或'\n'。在引号内,除了换行符(newline)和未转义的单引号(unescaped single quote),任何字符都可以出现。一个单引号字符代表该字符本身的Unicode值,而以反斜线开始的多字符序列则以各种格式编码。
最简单的形式代表引号内的单个字符;由于Go源文本是以UTF-8编码的Unicode字符,多个UTF-8编码的字节可能代表一个整数值。例如,字面意义上的'a'持有一个字节,代表字面意义上的a,Unicode U+0061,数值为0x61,而'ä'持有两个字节(0xc3 0xa4),代表字面意义上的a-dieresis,U+00E4,数值为0xe4。
一些反斜线转义允许任意的值被编码为ASCII文本。有四种方法可以将整数值表示为数字常量:
\x后面正好有两个十六进制数字;\u后面正好有四个十六进制数字;\U后面正好有八个十六进制数字,以及- 一个普通的反斜线
\后面正好有三个八进制数字。
在每种情况下,字面的值都是由相应基数的数字代表的值。
虽然这些表示方法都是一个整数,但它们的有效范围不同。八进制转义必须代表0到255之间的值。十六进制转义在结构上满足这一条件。转义\u和\U代表Unicode码点,所以在它们里面有些值是非法的,特别是那些高于0x10FFFF的值和 surrogate halves 的值。
在反斜线之后,某些单字符转义表示特殊的值:
\a U+0007 alert or bell
\b U+0008 backspace
\f U+000C form feed
\n U+000A line feed or newline
\r U+000D carriage return => 回车
\t U+0009 horizontal tab => 水平制表符
\v U+000B vertical tab => 垂直制表符
\\ U+005C backslash => 反斜线
\' U+0027 single quote (valid escape only within rune literals) => 单引号(仅在符文字面量内有效转义)
\" U+0022 double quote (valid escape only within string literals) => 双引号(仅在字符串字面值内有效转义)
在符文字面量中的反斜线后面无法识别的字符是非法的。
rune_lit = "'" ( unicode_value | byte_value ) "'" .
unicode_value = unicode_char | little_u_value | big_u_value | escaped_char .
byte_value = octal_byte_value | hex_byte_value .
octal_byte_value = `\` octal_digit octal_digit octal_digit .
hex_byte_value = `\` "x" hex_digit hex_digit .
little_u_value = `\` "u" hex_digit hex_digit hex_digit hex_digit .
big_u_value = `\` "U" hex_digit hex_digit hex_digit hex_digit
hex_digit hex_digit hex_digit hex_digit .
escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) .
'a'
'ä'
'本'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'
'\'' // rune literal containing single quote character
'aa' // illegal: too many characters
'\k' // illegal: k is not recognized after a backslash
'\xa' // illegal: too few hexadecimal digits
'\0' // illegal: too few octal digits
'\400' // illegal: octal value over 255
'\uDFFF' // illegal: surrogate half
'\U00110000' // illegal: invalid Unicode code point
String literals 字符串字面量
字符串字面量表示通过连接字符序列获得的字符串常量。有两种形式:原始字符串字面量和解释字符串字面量。
原始字符串字面量是反引号之间的字符序列,如`foo`。在引号内,任何字符都可以出现,除了反引号。原始字符串字面量的值是由引号之间未解释的(隐含的UTF-8编码)字符组成的字符串;特别是,反斜线没有特殊含义,字符串可以包含新行。原始字符串字面量内的回车字符(’\r’)会从原始字符串值中丢弃。
解释字符串字面量是双引号之间的字符序列,如 “bar”。在引号内,除了换行和未转义的双引号,任何字符都可以出现。引号之间的文字构成了字面量的值,反斜线转义的解释与符文字面量中的解释相同(除了\'是非法的,\"是合法的),限制也相同。三位数的八进制(\nnn)和两位数的十六进制(\xnn)转义代表结果字符串的单个字节;所有其他转义表示单个字符的(可能是多字节的)UTF-8编码。因此,在一个字符串字面中,\377和\xFF代表值为0xFF=255的单个字节,而ÿ、\u00FF、\U000000FF和 \xc3\xbf代表字符U+00FF的UTF-8编码的两个字节0xc3 0xbf。
string_lit = raw_string_lit | interpreted_string_lit .
raw_string_lit = "`" { unicode_char | newline } "`" .
interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
`abc` // same as "abc"
`\n
\n` // same as "\\n\n\\n"
"\n"
"\"" // same as `"`
"Hello, world!\n"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
"\uD800" // illegal: surrogate half
"\U00110000" // illegal: invalid Unicode code point
这些示例都表示相同的字符串:
"日本語" // UTF-8 input text
`日本語` // UTF-8 input text as a raw literal
"\u65e5\u672c\u8a9e" // the explicit Unicode code points
"\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // the explicit UTF-8 bytes
如果源代码将一个字符表示为两个码点,例如涉及重音和字母的组合形式,如果放在符文字面量中,结果将是一个错误(它不是一个单一码点),如果放在字符串字面量中,将显示为两个码点。
1.1.5 - 常量
Constants 常量
有布尔常量、符文常量、整数常量、浮点常量、复数常量和字符串常量。符文、整数、浮点和复数常量统称为数值常量。
常量值由一个符文字面量、整数字面量、浮点数字面量、虚数字面量或字符串字面量,表示常量的标识符,常量表达式,结果为常量的转换,或一些内置函数的结果值表示,如unsafe.Sizeof应用于某些值,cap或len应用于一些表达式,real和imag应用于复数常量,complex应用于数值常量。布尔真值由预先声明的常数true和false表示。预先声明的标识符iota表示一个整数常量。
通常,复数常量是常量表达式的一种形式,将在该节中讨论。
数值常量表示任意精度的精确值,不会溢出。因此,不存在表示IEEE-754负零、无穷大和非数字值的常量。
常量可以是有类型的的或无类型的。字面常量、true、false、iota,以及某些只包含无类型的常量操作数的常量表达式是无类型的。
常量可以通过常量声明或转换显式地给出类型,也可以在变量声明、赋值语句 、作为表达式的操作数时,隐式赋予类型。如果常量值不能被表示为相应类型的值,那就是一个错误。如果类型是一个类型参数,常量将被转换为类型参数的一个非常量值。
一个无类型常量有一个默认的类型,该类型是在需要类型化值的上下文中隐式转换为的类型,例如,在一个短变量声明中,如i := 0,没有明确的类型。无类型常量的默认类型分别是bool, rune, int, float64, complex128或string,具体取决于它是一个布尔型常量、rune型常量、整数型常量、浮点型常量、复数型常量还是字符串型常量。
实现限制:尽管数值常量在语言中具有任意的精度,但编译器可以使用有限精度的内部表示法来实现它们。也就是说,每个实现都必须:
- 用至少256位来表示整数常量。
- 用至少256位的尾数和至少16位的有符号二进制指数来表示浮点常量,包括复数常量的对应部分。
- 如果不能精确表示一个整数常量,则给出一个错误。
- 如果由于溢出而无法表示一个浮点常量或复数常量,则给出一个错误。
- 如果由于精度的限制,无法表示一个浮点常量或复数常量,则四舍五入到最接近的可表示常量。
这些要求既适用于字面常量,也适用于常量表达式的计算结果。
1.1.6 - 变量
Variables 变量
变量是用于保存值的存储位置。允许值的集合是由变量的类型决定的。
变量声明 、函数参数和结果、函数声明或函数字面量的签名为指定的变量保留存储空间。调用内置函数new或获取复合字面量的地址会在运行时为变量分配存储空间。这样的匿名变量是通过(可能是隐式的)指针间接引用的。
数组、切片和结构体等类型的结构化变量具有可以被单独寻址的元素和字段。每个这样的元素都像一个变量。
变量的静态类型(或仅仅是类型)是在其声明中给出的类型、在new调用或复合字面量中提供的类型、或是结构化变量的元素的类型。接口类型的变量也有一个独特的动态类型,它是运行时分配给变量的值的(非接口)类型(除非该值是预先声明的标识符nil,它没有类型)。在执行过程中,动态类型可能会发生变化,但是存储在接口变量中的值总是可以赋给变量的静态类型。
|
|
变量的值是通过在表达式中引用该变量来检索的;它是最近分配给该变量的值。如果一个变量还没有被赋值,它的值就是其类型的零值。
1.1.7 - 类型
Types 类型
类型决定了一组值以及特定于这些值的操作和方法。如果类型具有类型名称,则可以用类型名称表示。如果类型是泛型,则后面必须跟类型参数。还可以使用类型字面量指定类型,它由现有类型组成一个类型。
Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" .
TypeName = identifier | QualifiedIdent .
TypeArgs = "[" TypeList [ "," ] "]" .
TypeList = Type { "," Type } .
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
SliceType | MapType | ChannelType .
该语言预先声明了某些类型的名称。其他类型是通过类型声明或类型参数列表引入的。复合类型:数组、结构体、指针、函数、接口、切片、映射和通道类型 —— 可以用类型字面量来构造。
预先声明的类型、已定义的类型和类型参数被称为命名类型。如果别名声明中给出的类型是命名类型,则别名也表示一个(新的)命名类型。
Boolean types 布尔型
布尔型表示由预先声明的常量true和false表示的一组布尔真值。预先声明的布尔类型是bool;它是一个已定义的类型。
Numeric types 数值型
整数类型、浮点类型或复数类型分别表示整数、浮点或复数的值的集合。它们被统称为数值类型。预先声明的与体系结构无关的数值类型有:
|
|
The value of an n-bit integer is n bits wide and represented using two’s complement arithmetic. =>仍有疑问??
一个n位整数的值是n位宽,并用二进制补码运算法(two’s complement arithmetic)表示。
还有一组预先声明的整数类型,它们具有特定于实现的大小:
|
|
为了避免可移植性问题,所有的数值类型都是已定义的类型,因此除了 byte (uint8的别名)和 rune (int32的别名)之外,它们是截然不同的。 当不同的数值类型在表达式或赋值中混合使用时,需要进行显式转换。例如,int32和int不是相同类型,尽管它们在一个特定的体系结构上可能具有相同的大小。
String types 字符串型
字符串类型表示字符串值的集合。字符串值是字节序列(可能为空)。字节数被称为字符串的长度,并且永远不会是负数。字符串是不可变的:一旦创建,就不可能改变字符串的内容。预先声明的字符串类型是string;它是一种已定义的类型。
可以使用内置函数 len 查找字符串 s 的长度。如果字符串是常量,那么长度就是编译时常量。字符串的字节可以通过整数索引0到len(s)-1来访问。取这样一个元素的地址是非法的;如果s[i]是字符串的第i个字节,那么&s[i]是无效的。
Array types 数组型
数组是单类型的元素组成的编号序列,称为元素类型。元素的数量被称为数组的长度,并且永远不会是负数。
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = Type .
长度是数组类型的一部分;它必须求值为一个非负常数,该常数可由 int 类型的值表示。数组a的长度可以用内置函数len发现。元素可以通过整数索引0到len(a)-1进行寻址。数组类型总是一维的,但是可以组成多维类型。
|
|
Slice types 切片型
切片是底层数组的连续段的描述符,并提供对该数组中编号的元素序列的访问。切片类型表示其元素类型的所有数组切片的集合。元素的数量被称为切片的长度,并且永远不会是负数。一个未初始化的切片的值是nil。
SliceType = "[" "]" ElementType .
切片s的长度可以通过内置函数len发现;与数组不同,它在运行过程中可能会发生变化。元素可以通过整数索引0到len(s)-1进行寻址。给定元素的切片索引可能小于底层数组中同一元素的索引。
切片一旦被初始化,总是与保存其元素的底层数组相关联。因此,一个切片与它的底层数组和同一数组的其他切片共享存储;相反,不同的数组总是表示不同的存储。
切片的底层数组可以超过切片的末端。容量是对这一范围的衡量:它是切片的长度和切片之外的数组长度之和;可以通过从原始切片切割一个新的切片来创建一个达到这个容量的切片。使用内置函数 cap(a)可以发现切片 a 的容量。
可以使用内置函数make来创建一个给定元素类型T的新的、初始化的切片值,该函数接受一个切片类型和指定长度和可选容量的参数。用make创建的切片总是分配一个新的、隐藏的数组,返回的切片值指向该数组。也就是说,执行
|
|
产生的切片与分配一个数组并对其进行切片是一样的,所以这两个表达式是等同的:
|
|
和数组一样,切片总是一维的,但可以通过组合来构造更高维的对象。对于数组的数组,内部数组在结构上总是相同的长度;但是对于切片的切片(或切片的数组),内部长度可以动态变化。此外,内部切片必须被单独初始化。
Struct types 结构体型
结构体是一个命名元素(称为字段)的序列,,每个字段都有一个名称和一个类型。字段名可以显示地指定(IdentifierList)或隐含地指定(EmbeddedField)。在一个结构体中,非空白字段名必须是唯一的。
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName [ TypeArgs ] .
Tag = string_lit .
// An empty struct.
struct {}
// A struct with 6 fields.
struct {
x, y int
u float32
_ float32 // padding
A *[]int
F func()
}
一个声明了类型但没有明确字段名的字段被称为嵌入式字段。嵌入字段必须被指定为一个类型名T或一个指向非接口类型名*T的指针,而且T本身不能是一个指针类型。未限定类型名作为字段名。
|
|
下面的声明是非法的,因为字段名在一个结构体类型中必须是唯一的。
|
|
如果x.f是表示字段或方法f的合法选择器,那么结构体x中的嵌入式字段或方法f被称为(自动)提升(的字段或方法)。
被提升的字段与结构体中的普通字段一样,只是它们不能在结构体的复合字面量中作为字段名使用。
给定一个结构体类型S和一个命名类型T,提升的方法被包含在结构体的方法集中,如下所示:
- 如果
S包含一个嵌入式字段T,那么S和*S的方法集都包括带有接收器T的提升方法,*S的方法集也包括带有接收器*T的提升方法。 - 如果
S包含一个嵌入式字段*T,那么S和*S的方法集都包括带有接收器T或*T的提升方法。
一个字段声明后面可以有一个可选的字符串字面量标签,它成为相应字段声明中所有字段的属性。一个空的标签字符串等同于一个不存在标签。标签通过反射接口可见,并参与结构体的类型标识,但在其他情况下被忽略。
|
|
Pointer types 指针型
指针类型表示指向给定类型(称为指针的基本类型)变量的所有指针的集合。一个未初始化的指针的值是nil。
|
|
Function types 函数型
函数类型表示具有相同参数类型和结果类型的所有函数的集合。一个函数类型的未初始化变量的值是nil。
FunctionType = "func" Signature .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
在参数或结果的列表中,名称(IdentifierList)必须全部存在或全部不存在。如果存在(名称),每个名称代表指定类型的一个项(参数或结果),并且签名中所有非空白的名称必须是唯一的。如果不存在(名称),每个类型代表该类型的一个项。参数和结果列表总是用括号表示,但如果正好仅有一个未命名的结果,则可以写成未括号的类型。
在函数签名中的最后一个传入参数可以有一个类型前缀 ...。有这样一个参数的函数被称为 variadic (可变参数函数),可以用零个或多个参数来调用该函数。
|
|
Interface types 接口型
接口类型定义了一个类型集。接口类型的变量可以存储该接口类型集中的任何类型的值。这样的类型被称为实现了该接口。未初始化的接口类型变量的值是nil。
InterfaceType = "interface" "{" { InterfaceElem ";" } "}" .
InterfaceElem = MethodElem | TypeElem .
MethodElem = MethodName Signature .
MethodName = identifier .
TypeElem = TypeTerm { "|" TypeTerm } .
TypeTerm = Type | UnderlyingType .
UnderlyingType = "~" Type .
接口类型由接口元素列表指定。接口元素是一个方法或一个类型元素,其中类型元素是一个或多个类型术语的联合。类型术语可以是一个单一类型,也可以是一个单一的底层类型。
Basic interfaces 基本接口
在其最基本的形式中,接口指定了一个(可能是空的)方法列表。由这样一个接口定义的类型集是实现所有这些方法的类型集,而相应的方法集则完全由这个接口指定的方法组成。那些类型集可以完全由一个方法列表来定义的接口被称为基本接口。
|
|
|
|
多个类型可以实现一个(相同的)接口。例如,如果两个类型S1和S2的方法设置为
|
|
(其中T代表S1或S2),那么File接口就由S1和S2实现,而不管S1和S2可能有其他方法或共享什么其他方法。
作为接口类型集成员的每个类型都实现了该接口。任何给定的类型都可以实现几个不同的接口。例如,所有类型都实现空接口 (interface {}),它代表所有(非接口)类型的集合:
|
|
为了方便,预先声明的类型any是空接口的别名。
类似地,考虑这个接口规范,它出现在定义名为 Locker 的接口的类型声明中:
|
|
如果S1和S2也实现了
|
|
他们就实现了Locker接口和File接口。
Embedded interfaces 嵌入式接口
接口T可以使用(可能是限定的)接口类型名称E作为接口元素。这就是在 T 中嵌入接口 E。T的类型集是由T的显式声明方法定义的类型集和T的嵌入接口的类型集的交集。换句话说,T的类型集是实现T的所有显式声明的方法以及E的所有方法的所有类型的集合。
|
|
|
|
General interfaces 通用接口
在最通用的形式下,接口元素也可以是一个任意类型的术语T,或者是一个指定底层类型T的~T形式的术语,或者是术语t1|t2|...|tn的联合。与方法规范一起,这些元素能够精确地定义一个接口的类型集,如下所示:
- 空接口的类型集是
所有非接口类型的集合。 - 非空接口的类型集是其接口元素的类型集的交集。
- 方法规范的类型集是其方法集包括该方法的
所有非接口类型的集合。 - 非接口类型术语的类型集是仅由该类型组成的集合。
- 形式为
~T的术语的类型集是其底层类型为T的所有类型的集合。 - 术语
t1|t2|...|tn的联合体类型集是各术语类型集的联合。
量化 “所有非接口类型的集合 “不仅指手头程序中声明的所有(非接口)类型,还指所有可能程序中的所有可能类型,因此是无限的。类似地,给定实现某个特定方法的所有非接口类型的集合,这些类型的方法集的交集将正好包含该方法,即使手头的程序中的所有类型总是将该方法与另一个方法配对。
通过构造,一个接口的类型集永远不会包含一个接口类型。
|
|
在形式为~T的术语中,T的底层类型必须是它自己,而且T不能是一个接口。
|
|
联合元素表示类型集的联合:
|
|
形式为T或~T的术语中的类型T不能是类型参数,所有非接口术语的类型集必须是成对不相交的(类型集的成对交集必须为空)。给定一个类型参数P:
|
|
实现限制:联合(有多个术语)不能包含预先声明的标识符comparable或指定方法的接口,或嵌入comparable或指定方法的接口。
非基本接口只能作为类型约束使用,或者作为其他接口的元素作为约束使用。它们不能作为值或变量的类型,也不能作为其他非接口类型的组成部分。
|
|
接口类型 T 不能嵌入任何递归地包含或嵌入 T 的类型元素。
|
|
Implementing an interface 实现一个接口
如果类型T实现了接口I,则
T不是接口,并且是I类型集的元素;或者T是接口,并且T的类型集是I的类型集的子集。
如果T实现了一个接口,那么T类型的值就实现了该接口。
Map types 映射型
映射是一个无序的元素组,由一种类型的元素(称为元素类型)组成,由另一种类型的唯一键集(称为键类型)进行索引。一个未初始化的映射的值是nil。
MapType = "map" "[" KeyType "]" ElementType .
KeyType = Type .
比较运算符==和!=必须为键类型的操作数完全定义;因此键类型不能是函数、映射或切片。如果键类型是接口类型,则必须为动态键值定义这些比较运算符;失败将导致运行时恐慌(run-time panic)。
|
|
映射元素的数量被称为它的长度。对于一个map m来说,它可以用内置函数len来发现,并且在运行过程中可能会改变。在运行过程中可以用赋值添加元素,用索引表达式检索元素;可以用内置函数delete删除元素。
使用内置函数 make 创建一个新的空 map 值,它使用 map 类型和一个可选的容量提示作为参数:
|
|
初始容量不限制其大小:映射会增长以容纳其中存储的项数,但nil映射除外。nil映射等同于空映射,只是不能添加任何元素。
Channel types 通道型
通道为并发执行函数提供了一种机制,通过发送和接收指定元素类型的值进行通信。未初始化的通道的值是nil。
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
可选的<-操作符指定了通道的方向:发送或接收。如果指定了方向,则该通道是定向的,否则是双向的。通过赋值或显式转换,通道可以被限制为仅发送或仅接收。
|
|
<- 操作符尽可能与最左边的 chan 相关联:
|
|
可以使用内置函数 make 创建一个新的、初始化的 channel 值,它以channel 类型和可选的容量作为参数:
|
|
容量(以元素数量为单位)设置通道中缓冲区的大小。如果容量为零或没有指定,则通道是无缓冲的,只有当发送方和接收方都准备好时,通信才会成功。否则,如果缓冲区不满(可继续发送)或不是空的(可继续接收) ,通道会将数据缓冲起来,并且通信在没有阻塞的情况下成功。一个nil通道不能用于通信。
!!! info “引用其他书籍” 以下摘自《Go语言精进之路》第34条 了解channel的妙用 第348页。 与无缓冲channel 不同,带缓冲channel 可以通过带有 capacity 参数的内置make 函数创建:c:= make(chan T, capctity) 由于带缓冲channel 的运行时层实现带有缓冲区,因此对带有缓冲channel的发送操作在缓冲区未满、接收操作在缓冲区非空的情况下是异步的(发送或接收无需阻塞等待)。也就是说,对一个带缓冲channel,在缓冲区无数据或有数据但未满的情况下,对其进行发送操作的goroutine不会阻塞;在缓冲区已满的情况下,对其进行发送操作的goroutine会阻塞;在缓冲区为空的情况下,对其进行接收操作的goroutine亦会阻塞。
通道可以用内置函数close来关闭。接收操作符的多值赋值形式可以用来判断数据是否在通道关闭之前发送出去。
任意数量的goroutines都可以通过发送语句、接收操作以及对内置函数cap和len的调用,来操作一个通道。通道是一个先入先出的队列。例如,如果一个goroutine在通道上发送数据,第二个goroutine接收这些数据,那么这些数据将按照发送的顺序被接收。
1.1.8 - 类型和值的属性
Properties of types and values 类型和值的属性
Underlying types 底层类型/基本类型
每个类型T都有一个底层类型。如果T是预先声明的布尔型、数值型或字符串型之一,或者是一个类型字面量,那么对应的底层类型就是T本身。否则,T的底层类型是T在其声明中所指的类型的底层类型。对于类型参数,则是其类型约束的底层类型,它总是一个接口。
type (
A1 = string
A2 = A1
)
type (
B1 string
B2 B1
B3 []B1
B4 B3
)
func f[P any](x P) { … }
string、 A1、 A2、 B1和 B2的底层类型是 string。[]B1、B3和B4的底层类型是[]B1。P的底层类型是interface{}。
Core types 核心类型
每个非接口类型T都有一个核心类型,它与T的底层类型相同。
如果满足以下条件之一,那么接口T就有一个核心类型:
其他接口都没有核心类型。
接口的核心类型取决于满足的条件:
- 类型
U;或者 - 如果
T只包含双向通道,则为类型chan E;或者为chan<- E或<-chan E类型,这取决于现存定向信道的方向。
具有核心类型的接口的示例:
type Celsius float32
type Kelvin float32
interface{ int } // int
interface{ Celsius|Kelvin } // float32
interface{ ~chan int } // chan int
interface{ ~chan int|~chan<- int } // chan<- int
interface{ ~[]*data; String() string } // []*data
没有核心类型的接口的示例:
interface{} // no single underlying type
interface{ Celsius|float64 } // no single underlying type
interface{ chan int | chan<- string } // channels have different element types
interface{ <-chan int | chan<- int } // directional channels have different directions
一些操作(切片表达式、追加和复制)依赖于稍微宽松的核心类型形式,这些核心类型接受字节切片和字符串。具体来说,如果正好有两种类型,[]byte和string,它们是接口T的类型集中所有类型的底层类型,那么T的核心类型就被称为bytestring。
具有bytestring核心类型的接口的例子:
interface{ int } // int (same as ordinary core type) => int (与普通核心类型相同)
interface{ []byte | string } // bytestring
interface{ ~[]byte | myString } // bytestring
注意bytestring不是一个真正的类型;它不能用来声明变量(是由其他类型组成的)。它的存在只是为了描述一些从字节序列中读取的操作的行为,这些字节序列可能是字节切片或字符串。
Type identity 类型一致性
两种类型要么相同,要么不同。
命名类型总是与任何其他类型不同。否则,如果两个类型的底层类型字面量在结构上是一致的,那么这两个类型就是相同的;也就是说,它们有相同的字面量结构,相应的组成部分拥有一致的类型。详细来说:
- 如果两个数组类型有一致的元素类型和相同的数组长度,那么它们就是一致的。
- 如果两个切片类型有一致的元素类型,那么它们就是一致的。
- 如果两个结构体类型具有相同的字段序列,并且相应的字段具有一致的名称、一致的类型和一致的标签,那么它们就是一致的。来自不同包的不可导出的字段名总是不同的。
- 如果两个指针类型有一致的基本类型,那么它们就是一致的。
- 如果两个函数类型有相同数量的参数和结果值,并且相应的参数和结果类型是相同的,并且两个函数要么都是可变的,要么都不是。参数和结果名称不需要匹配。
- 如果两个接口类型定义了相同的类型集,那么它们就是一致的。
- 如果两个映射类型有一致的键和元素类型,它们就是一致的。
- 如果两个通道类型有一致的元素类型和相同的方向,那么它们是一致的。
- 如果两个实例化的类型的定义类型和所有类型参数都是一致的,那么它们就是一致的。
给出声明:
type (
A0 = []string
A1 = A0
A2 = struct{ a, b int }
A3 = int
A4 = func(A3, float64) *A0
A5 = func(x int, _ float64) *[]string
B0 A0
B1 []string
B2 struct{ a, b int }
B3 struct{ a, c int }
B4 func(int, float64) *B0
B5 func(x int, y float64) *A1
C0 = B0
D0[P1, P2 any] struct{ x P1; y P2 }
E0 = D0[int, string]
)
这些类型是一致的:
A0, A1, and []string
A2 and struct{ a, b int }
A3 and int
A4, func(int, float64) *[]string, and A5
B0 and C0
D0[int, string] and E0
[]int and []int
struct{ a, b *B5 } and struct{ a, b *B5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
B0和B1是不同的,因为它们是由不同的类型定义所创建的新类型;func(int, float64) *B0和func(x int, y float64) *[]string是不同的,因为B0与[]string是不同的;P1和P2是不同,因为它们是不同的类型参数。D0[int, string]和struct{ x int; y string }是不同的,因为前者是一个实例化的定义类型,而后者是一个类型字面量(但它们仍然是可分配的)。
Assignability 可分配性
在以下这些情况中,V类型的值x是可以分配给T类型的变量("x可以分配给T"):
V和T是一致的。V和T有一致的底层类型,但不是类型参数,并且V或T中至少有一个不是命名类型。V和T是具有一致元素类型的通道类型,V是一个双向通道,并且V或T中至少有一个不是命名类型。T是接口类型,但不是一个类型参数,并且x实现了T。x是预先声明的标识符nil,并且T是一个指针、函数、切片、映射、通道或接口类型,但不是一个类型参数。x是可由T类型的值表示的非类型化的常量。
除此之外,如果x的类型V或T是类型参数,并且满足以下条件之一,那么x也可以分配给类型T的变量:
x是预先声明的标识符nil,T是类型参数,并且x可以分配给T的类型集中的每个类型。V不是命名类型,T是一个类型参数,并且x可以分配给T的类型集中的每个类型。V是类型参数,T不是命名类型,而V的类型集中的每个类型的值都可以分配给T。
Representability 可表示性
如果满足以下条件之一,常量x就可以被T类型的值所表示,其中T不是类型参数:
x在由T所确定的值的集合中。T是浮点类型,并且x可以被舍入到T的精度而不会溢出。四舍五入使用的是IEEE 754的四舍五入到偶数的规则,但IEEE的负0被进一步简化为无符号0。请注意,常量值绝不会出现IEEE负零、NaN或无穷大。T是复数类型,x的组成real(x)和imag(x)可以用T的组成类型(float32或float64)的值表示。
如果T是类型参数,并且x可以由T的类型集中的每个类型的值来表示,那么x就可以由T类型的值来表示。
x T x is representable by a value of T because
'a' byte 97 is in the set of byte values
97 rune rune is an alias for int32, and 97 is in the set of 32-bit integers
"foo" string "foo" is in the set of string values
1024 int16 1024 is in the set of 16-bit integers
42.0 byte 42 is in the set of unsigned 8-bit integers
1e10 uint64 10000000000 is in the set of unsigned 64-bit integers
2.718281828459045 float32 2.718281828459045 rounds to 2.7182817 which is in the set of float32 values
-1e-1000 float64 -1e-1000 rounds to IEEE -0.0 which is further simplified to 0.0
0i int 0 is an integer value
(42 + 0i) float32 42.0 (with zero imaginary part) is in the set of float32 values
x T x is not representable by a value of T because
0 bool 0 is not in the set of boolean values
'a' string 'a' is a rune, it is not in the set of string values
1024 byte 1024 is not in the set of unsigned 8-bit integers
-1 uint16 -1 is not in the set of unsigned 16-bit integers
1.1 int 1.1 is not an integer value
42i float32 (0 + 42i) is not in the set of float32 values
1e1000 float64 1e1000 overflows to IEEE +Inf after rounding
Method sets 方法集
类型的方法集确定了该类型的操作数可以调用的方法。每个类型都有一个与之相关的(可能是空的)方法集。
- 定义类型
T的方法集包括所有用接收器类型T声明的方法。 - 指向定义类型
T的指针(T既不是指针也不是接口)的方法集是与接收器*T或T一起声明的所有方法的集合。 - 接口类型的方法集是该接口类型集中每个类型的方法集的交集(最终的方法集通常只是接口中声明的方法集)。
进一步的规则,应用于包含嵌入字段的结构体(和结构体指针),会在关于结构体类型的章节中描述。任何其他类型都有一个空的方法集。
1.1.9 - 块
Blocks 块
块是在一对匹配的大括号内的声明和语句(一个可能是空的)序列。
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
源代码中除了显式块之外,还有隐式块:
- 包含所有的Go源码文本的
universe block。 - 每个包都有一个
package block,包含该包的所有 Go 源代码。 - 每个文件都有一个
file block,包含该文件中的所有Go 源代码。 - 每个 “if"、"for “和 “switch “语句都被认为是在自己的隐式块中。
- “switch“或 “select “语句中的每个子句都是一个隐式块。
块是可以嵌套并影响着作用域。
1.1.10 - 声明和作用域
Declarations and scope 声明和作用域
声明将一个非空白的标识符绑定到一个常量、类型、类型参数、变量、函数、标签或包。程序中的每个标识符都必须被声明。没有一个标识符可以在同一个块中声明两次,也没有一个标识符可以同时在文件块和包块中声明。
空白标识符(即_)可以像其他标识符一样在声明中使用,但它不引入绑定,因此不被声明。在包块中,标识符init只能用于init函数的声明,和空白标识符一样,它不会引入一个新的绑定。
Declaration = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
声明标识符的作用域是源文本的范围,其中标识符表示指定的常量、类型、变量、函数、标签或包。
Go在词法使用块来确定作用域:
- 预先声明的标识符的作用域是
universe block。 - 表示常量、类型、变量或函数(但不是方法)的标识符在顶层(任何函数之外)声明的作用域是
package block。 - 导入的包的包名的作用域是在导入声明的文件的
file block。 - 表示方法接收器、函数参数或结果变量的标识符的作用域是函数体。
- 表示函数的类型参数或由方法接收器声明的标识符的作用域从函数名称之后开始,在函数体的末端结束。
- 表示类型的类型参数的标识符的作用域从类型的名称之后开始,在TypeSpec的末尾结束。=>仍有疑问??
- 在函数中声明的常量或变量标识符的作用域从ConstSpec或VarSpec(ShortVarDecl用于短变量声明)的末尾开始,在最里面的包含块的末尾结束。
- 在函数中声明的类型标识符的作用域从TypeSpec中的标识符开始,在最内层的包含块的末端结束。
在块中声明的标识符可以在内部块中被重新声明。当内部声明的标识符在作用域内时,它表示内部声明所声明的实体。
包语句不是一个声明;包名不出现在任何作用域中。它的目的是识别属于同一包的文件,并为导入声明指定默认的包名。
Label scopes 标签作用域
标签由标签语句声明,用于 “break"、"continue “和 “goto “语句中。定义一个从不使用的标签是非法的。与其他标识符不同的是,标签没有块作用域,也不会与不是标签的标识符冲突。标签的作用域是声明它的函数的主体,不包括任何嵌套函数的主体。
Blank identifier 空白标识符
空白标识符由下划线字符_表示。它是一个匿名的占位符,而不是普通的(非空白)标识符,在声明中具有特殊的意义,可以作为操作数,也可以在赋值语句中。
Predeclared identifiers 预先声明的标识符
下列标识符是在universe block中隐式声明的:
Types:
any bool byte comparable
complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
Constants:
true false iota
Zero value:
nil
Functions:
append cap close complex copy delete imag len
make new panic print println real recover
Exported identifiers 可导出的标识符
标识符可以被导出,以允许从另一个包访问它。一个标识符在以下两种情况下被导出:
- 标识符的第一个字符是一个Unicode大写字母(Unicode字符类别Lu);并且
- 该标识符在package block中被声明,或者它是一个字段名或方法名。
所有其他标识符都不被导出。
Uniqueness of identifiers 标识符的唯一性
给定一组标识符,如果一个标识符与这组标识符中的每一个都不同,则称为唯一。如果两个标识符的拼写不同,或者它们出现在不同的包中并且不被导出,那么它们就是不同的。否则,它们是相同的。
Constant declarations 常量声明
常量声明将一列标识符(常量的名称)与一列常量表达式的值绑定。标识符的数量必须等于表达式的数量,左边的第n个标识符被绑定到右边的第n个表达式的值上。
ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
如果有指定类型,则所有常量都采用该指定的类型,并且表达式必须可以赋值给该类型,该类型不能是一个类型参数。
如果类型被省略,则常量采取相应表达式的类型。
如果表达式的值是无类型的(untyped)常量,那么声明的常量仍然是无类型,并且常量标识符表示该无类型的常量值。例如,如果表达式是一个浮点字面量,那么常量标识符就表示一个浮点常量,即使字面量的小数部分是0。
|
|
在括号内的const声明列表中,除了第一个ConstSpec外的任何表达式都可以省略表达式列表。这样的空列表相当于对前面第一个非空表达式列表及其类型(如果有的话)进行文本替换。因此,省略表达式列表等同于重复前面的列表。标识符的数量必须等于上一个列表中表达式的数量。与iota 常量生成器一起使用,此机制允许对连续值进行轻量级声明。
|
|
Iota
在常量声明中,预先声明的标识符iota表示连续的无类型整数常量。它的值是该常量声明中各个 ConstSpec 的索引,从零开始。它可以被用来构造一组相关的常量:
|
|
根据定义,在同一个ConstSpec中(可以认为是同一行中)多次使用iota都有相同的值:
|
|
最后这个例子利用了最后一个非空表达式列表的隐式重复。
Type declarations 类型声明
类型声明将一个标识符,即类型名称,与一个类型绑定。类型声明有两种形式:别名声明和类型定义。
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
Alias declarations 别名声明
别名声明将一个标识符绑定到给定的类型上。
AliasDecl = identifier "=" Type .
在标识符的作用域内,它作为该类型的别名。
|
|
Type definitions 类型定义
类型定义创建了一个新的、不同的类型,其底层类型和操作与给定的类型相同,并将标识符,即类型名称绑定到它。
TypeDef = identifier [ TypeParameters ] Type .
这个新的类型被称为已定义类型。它与任何其他类型(包括它创建时使用的类型)不同。
|
|
一个已定义类型可以有与之相关的方法。这一新定义的类型不会继承绑定到给定类型的任何方法,但是接口类型或复合类型的元素的方法集保持不变。
|
|
类型定义可用于定义不同的布尔型、数值型或字符串型,并为它们绑定方法:
|
|
如果类型定义指定了类型参数,那么这个类型名称表示一个泛型。泛型在使用时必须被实例化。
|
|
In a type definition the given type cannot be a type parameter.
在一个类型定义中,给定的类型不能是一个类型参数。
|
|
泛型也可以有与之相关的方法。在这种情况下,方法接收器必须声明与泛型定义中存在的相同数量的类型参数。=>仍有疑问??
|
|
Type parameter declarations 类型参数声明
类型参数列表声明了一个泛型函数或类型声明的类型参数。类型参数列表看起来和普通的函数参数列表一样,除了类型参数名称必须全部出现,并且列表被括在方括号中,而不是花括号中。
TypeParameters = "[" TypeParamList [ "," ] "]" .
TypeParamList = TypeParamDecl { "," TypeParamDecl } .
TypeParamDecl = IdentifierList TypeConstraint .
列表中所有非空白的名字必须是唯一的。每个名字都声明了一个类型参数,这是一个新的且不同的命名类型,作为声明中一个(到目前为止)未知类型的占位符。类型参数在泛型函数或类型实例化时被替换为类型实参(type argument)。
[P any]
[S interface{ ~[]byte|string }]
[S ~[]E, E any]
[P Constraint[int]]
[_ any]
就像每个普通的函数参数都有一个参数类型一样,每个类型参数也有一个相应的被称为其类型约束的(元)类型。
当泛型的类型参数列表声明了一个带有约束条件C的单一类型参数P,从而使文本P C构成一个有效的表达式时,就会出现解析歧义:
|
|
在这些罕见的情况下,类型参数列表很难与表达式进行区别,导致该类型声明被解析为一个数组类型声明。为了解决这种歧义,可将约束嵌入到一个接口中或者在尾部使用逗号:
|
|
类型参数也可以通过与泛型相关的方法声明的接收器规范来声明。
Type constraints 类型约束
类型约束是一个接口,该接口定义了对应的类型参数所允许的一组类型实参,并控制该类型参数的值所支持的操作。
TypeConstraint = TypeElem .
如果约束是一个形式为interface{E}的接口字面量,其中E是一个嵌入的类型元素(不是方法),在类型参数列表中,为了方便起见,可以省略参数列表中封闭的interface{ … }:
|
|
预先声明的接口类型: comparable ,表示所有非接口类型的集合,这些类型是可比较的。具体来说,如果一个类型T实现了comparable:
T不是一个接口类型并且T支持操作==和!=;或者T是一个接口类型,并且T的类型集中的每个类型都实现了comparable。
尽管非类型参数的接口可以被比较(可能导致运行时恐慌),但它们也没有实现comparable。
|
|
comparable这一接口和(直接或间接)嵌入comparable的接口只能作为类型约束使用。它们不能成为值或变量的类型,或其他非接口类型的组成部分。
Variable declarations 变量声明
变量声明创建一个或多个变量,为它们绑定相应的标识符,并为每个变量设定一个类型和一个初始值。
|
|
如果变量声明时给出的是表达式列表,则变量将按照赋值语句的规则用表达式进行初始化。否则,每个变量被初始化为其零值。
如果变量声明时提供了类型,则每个变量都被指定为该类型。否则,每个变量都被设定为赋值中相应的初始化值的类型。如果该值是一个无类型的常量,它首先被隐式转换为其默认类型;如果它是一个无类型的布尔值,它首先被隐式转换为bool。预先声明的值nil不能用来初始化一个没有明确类型的变量。
|
|
实现限制:在函数体中声明一个变量,若该变量从未被使用,编译器可以认为它是非法的。
Short variable declarations 短变量声明
短变量声明使用的语法:
ShortVarDecl = IdentifierList ":=" ExpressionList .
它是带有初始化表达式但没有类型的常规变量声明的简写:
"var" IdentifierList "=" ExpressionList .
i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)
r, w, _ := os.Pipe() // os.Pipe() returns a connected pair of Files and an error, if any
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
与常规变量声明不同,短变量声明可以重新声明变量,前提是这些变量最初是在同一个块(如果该块是函数体,则是参数列表)中以相同的类型声明的,并且至少有一个非空白变量是新的。因此,重复声明只能出现在一个多变量的短声明中。重复声明并没有引入一个新的变量;它只是给原来的变量分配了一个新的值。:=左侧的非空白变量名必须是唯一的。
field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset) // redeclares offset
x, y, x := 1, 2, 3 // illegal: x repeated on left side of :=
短变量声明只能出现在函数内部。在某些情况下,如 “if"、"for “或 “switch “语句的初始化语句中,它们可以用来声明局部临时变量。
Function declarations 函数声明
函数声明将标识符(函数名称)绑定到函数。
FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
FunctionName = identifier .
FunctionBody = Block .
如果函数的签名声明了结果参数,那么函数体的语句列表必须以一个终止语句结束。
|
|
如果函数声明中指定了类型参数,那么函数名就表示一个泛型函数。在被调用或作为值使用之前,泛型函数必须先被实例化。
|
|
没有类型参数的函数声明可以省略函数体。这样的声明提供了一个在Go外部实现的函数的签名,比如一个汇编程序。
|
|
Method declarations 方法声明
方法是带有接收器的函数。方法声明将一个标识符,即方法名称,绑定到一个方法上,并将该方法与接收器的基本类型联系起来。
MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] .
Receiver = Parameters .
接收器是通过方法名前面的一个额外的参数部分指定的。该参数部分必须声明一个非可变参数,即接收器。它的类型必须是一个已定义类型T或者一个指向已定义类型T的指针,后面可能是一个用方括号括起来的类型参数名称列表[P1, P2, ...]。T被称为接收器的基本类型。接收器的基类型不能是一个指针或接口类型,并且它必须在与方法相同的包中定义。这个定义过程称为将该方法与其接收器基本类型绑定,该方法名只在T或*T类型的选择器中可见。
一个非空白的接收器标识符在方法签名中必须是唯一的。如果接收器的值没有在方法体中被引用,它的标识符可以在声明中被省略。这一规则与函数和方法的普通参数类似。
对于一个基本类型,绑定到它的非空白名称必须是唯一的。如果基本类型是一个结构类型,非空白的方法名和字段名必须是唯一的。
给出定义类型Point,其声明:
|
|
绑定了方法Length和Scale,接收器类型为*Point,对应基本类型Point。
If the receiver base type is a generic type, the receiver specification must declare corresponding type parameters for the method to use. This makes the receiver type parameters available to the method. Syntactically, this type parameter declaration looks like an instantiation of the receiver base type: the type arguments must be identifiers denoting the type parameters being declared, one for each type parameter of the receiver base type. The type parameter names do not need to match their corresponding parameter names in the receiver base type definition, and all non-blank parameter names must be unique in the receiver parameter section and the method signature. The receiver type parameter constraints are implied by the receiver base type definition: corresponding type parameters have corresponding constraints.
如果接收器的基本类型是一个泛型,接收器规范必须为要使用的方法声明相应的类型形参。这使得接收器的类型形参对该方法可用。从语法上讲,这个类型形参声明看起来就像接收器基本类型的实例化:类型实参必须是表示被声明的类型参数的标识符,接收器基本类型的每个类型形参各有一个。类型形参名无需匹配接收器基本类型定义中对应的形参名,并且所有非空白形参名在接收器形参部分和方法签名中必须是唯一的。接收器类型形参的约束是由接收器基本类型定义所隐含的:相应的类型形参有相应的约束。=> 仍有疑问??
|
|
1.1.11 - 表达式
Expressions 表达式
表达式通过将运算符和函数应用于操作数来规定值的计算。
Operands 操作数
操作数表示表达式中的基本值。操作数可以是一个字面量,一个表示常量、变量或函数的(可以是限定的)非空白标识符,或者一对圆括号内的表达式。
Operand = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent .
表示泛型函数的操作数名称后面可以跟一个类型实参列表;产生的操作数是一个实例化过的函数。
实现限制:若操作数的类型是具有空类型集的类型形参,则编译器不必报告错误。具有这种类型形参的函数不能被实例化;任何尝试都会导致实例化处的错误。
Qualified identifiers 限定标识符
限定标识符是以包名作为前缀限定的标识符。包名和标识符都不能是空白标识符(即_)。
QualifiedIdent = PackageName "." identifier .
限定标识符可以在不同包中访问一个标识符,但该标识符所在的包必须已经被导入。该标识符必须可被导出并在该包的package block中声明。
|
|
Composite literals 复合字面量
复合字面量每次被求值时都会构造新的复合值。它们由字面量的类型和一个由花括号组成的元素列表组成。每个元素可以选择在前面加上一个相应的键。
CompositeLit = LiteralType LiteralValue .
LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
SliceType | MapType | TypeName [ TypeArgs ] .
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
ElementList = KeyedElement { "," KeyedElement } .
KeyedElement = [ Key ":" ] Element .
Key = FieldName | Expression | LiteralValue .
FieldName = identifier .
Element = Expression | LiteralValue .
LiteralType 的核心类型T必须是一个结构体、数组、切片或映射类型(除了当类型是作为TypeName给出时,语法会强制执行这个约束)。元素和键的类型必须可分配给T类型的对应字段、元素和键类型;不需要进行额外的转换。
这里的键被解释为结构体字面量的字段名、数组字面量或切片字面量的索引、映射字面量的键。
对于映射字面量,所有的元素必须有一个键。用相同的字段名或常量键值指定多个元素是错误的。对于非常量的映射键,请参见关于求值顺序的章节。
对于结构体字面量来说,以下规则适用:
- 键必须是结构体类型中声明的字段名。
- 不包含任何键的元素列表必须按照字段的声明顺序为每个结构体字段列出一个元素。
- 如果任何元素有一个键,那么每个元素都必须有一个键。
- 包含键的元素列表不需要每个结构体字段都有一个元素。省略的字段将获得该字段类型的零值。
字面量可以省略元素列表;这样的字面量相当对其类型的求值为零值。- 为属于不在同一个包中的结构体(即该结构体在其他包中定义)的非可导出字段指定元素是错误的。
给定的声明:
|
|
我们可以这样写:
|
|
对于数组字面量和切片字面量,以下规则适用:
- 每个元素都有一个相关的整数索引,标记其在数组中的位置。
- 带键的元素使用该键作为其索引。键必须是一个可由
int类型的值表示的非负常数;如果它是有类型的,则它必须是整数类型。 - 不带键的元素使用前一个元素的索引加1。如果第一个元素没有键,它的索引是0。
对一个复合字面量取址会产生一个指向唯一变量的指针,该变量用字面量的值初始化。
|
|
请注意,切片或映射类型的零值与同一类型的初始化过但为空的值不同。因此,获取一个空切片或空映射复合字面量的地址与用new分配一个新的切片或映射值的效果不同。
|
|
数组字面量的长度是字面量类型中指定的长度。如果在字面量上提供的元素少于长度,缺少的元素将被设置为数组元素类型的零值。若提供的元素的索引值超出了数组的索引范围,将导致错误。标记法...指定的数组长度等于最大元素索引加1。
|
|
切片字面量描述了整个底层数组字面量。因此,切片字面量的长度和容量是最大元素索引加1。切片字面量的形式是:
|
|
是对数组进行切片操作的简写:
|
|
在一个数组、切片或映射类型T的复合字面量中,如果本身是复合字面量的元素或映射键与T的元素或键类型相同,则可以省略(元素或映射键的)相应的字面量类型。同样,当元素或键类型为*T时,作为复合字面量地址的元素或键可以省略&T。
|
|
当使用LiteralType的TypeName形式的复合字面量作为操作数出现在关键字和 “if"、"for “或 “switch “等语句块的左花括号之间,并且复合字面量没有被括在圆括号、方括号或花括号中时,会出现解析歧义。在这种罕见的情况下,字面量的左花括号被错误地解析为引入语句块的左花括号。为了解决这个问题,复合字面量必须出现在圆括号内。
|
|
有效的数组、切片和映射字面量的例子:
|
|
Function literals 函数字面量
函数字面量表示一个匿名函数。函数字面量不能声明类型参数。
|
|
函数字面量可以被分配给一个变量或直接调用。
|
|
函数字面量可以是闭包:它们可以引用外层函数中定义的变量。然后,这些变量在外层的函数和函数字面量之间共享,并且只要它们可以被访问,它们就可以一直存在。
Primary expressions 主表达式
主表达式是一元、二元表达式的操作数。
|
|
Selectors 选择器
|
|
表示值x(有时是*x;见下文)的字段或方法f。标识符f被称为(字段或方法)选择器;它不能是空白标识符。选择器表达式的类型是f的类型。若x是包名,请参见关于限定标识符一节。
选择器f可以表示类型T的f字段或f方法,也可以指代T的嵌入字段或嵌入方法f。在T的一个嵌入字段A中声明的字段或方法f的深度是A中f的深度加1。
以下规则适用于选择器:
- 对于类型为
T或*T(T不是指针或接口类型)的值x,x.f表示T中存在这样一个最浅深度的字段或方法f。如果不是恰好有仅有一个f在最浅深度的话,那么选择器表达式是非法的。 - 对于接口类型
I的值x,x.f表示动态值x的名为f的实际方法。如果在I的方法集中没有名为f的方法,那么选择器表达式是非法的。 - 作为例外,如果
x的类型是一个定义的指针类型,并且(*x).f是一个有效的表示一个字段(不是一个方法)的选择器表达式,那么x.f是(*x).f的简写。 - 在所有其它情况下,
x.f是非法的。 - 如果
x是值为nil的指针类型,并且x.f表示一个结构体字段,那么赋值或计算x.f会引起运行时恐慌。 - 如果
x是值为nil的接口类型,那么调用或计值x.f方法会引起运行时恐慌。
例如,给定声明:
|
|
则我们可以这样写:
|
|
但下面的内容是无效的:
|
|
Method expressions 方法表达式
如果M在类型T的方法集中,那么T.M是一个可以作为普通函数来调用的函数,其实参与M相同,不过其前缀有一个额外的(作为该方法的接收器的)实参。
MethodExpr = ReceiverType "." MethodName .
ReceiverType = Type .
考虑有两个方法的结构体类型T,方法一的接收器是T类型的Mv,方法二的接收器是*T类型的Mp。
|
|
表达式
|
|
产生一个与Mv等价的函数,但是它的第一个形参是一个明确的接收器;它的签名是:
|
|
该函数可以在带有一个明确接收器的情况下正常调用,因此如下这五种调用是等同的:
|
|
类似地,表达式
|
|
产生一个代表Mp的函数值,它的签名是:
|
|
对于一个带值接收器的方法,可以推导出一个带有明确指针接收器的函数,所以
|
|
产生了一个代表Mv的函数值,它的签名是:
|
|
Such a function indirects through the receiver to create a value to pass as the receiver to the underlying method; the method does not overwrite the value whose address is passed in the function call.
这样的函数通过接收器间接地创建了一个值,作为接收器传递给底层方法;该方法不会覆盖(其地址在函数调用中被传递的)那个值。=>仍有疑问??
The final case, a value-receiver function for a pointer-receiver method, is illegal because pointer-receiver methods are not in the method set of the value type.
最后一种情况,将一个带指针接收器的方法当做一个带值接收器的函数,是非法的,因为指针接收器的方法不在值类型的方法集中。=>仍有疑问??
从方法中推导出来的函数值是用函数调用语法来调用的;接收器被作为调用的第一个实参来提供。也就是说,f := T.Mv中的f是作为f(t, 7)被调用,而不是t.f(7)。构造一个绑定接收器的函数,可以使用函数字面量或方法值。
从接口类型的方法中推导出来函数值是合法的。这样的函数需要一个该接口类型的显式接收器。
Method values 方法值
如果表达式x有静态类型T,并且M在类型T的方法集中,那么x.M被称为一个方法值。方法值x.M是一个可调用的函数值,其实参与x.M的方法调用相同。表达式x在方法值的求值过程中被求值和保存;然后保存的副本被用作任何调用中的接收器上,这些调用可能在以后执行。
|
|
类型T既可以是接口类型,也可以是非接口类型。
如同上面对方法表达式的讨论,考虑一个有两个方法的结构体类型T,方法一的接收器是T类型的Mv,方法二的接收器是*T类型的Mp。
|
|
表达式
|
|
产生一个类型如下的函数值:
|
|
这两种调用是等价的:
|
|
同样地,表达式
|
|
产生一个类型如下的函数值:
|
|
和选择器一样,若对以值作为接收器的非接口方法,使用指针来引用,则(Go语言)将自动解除对该指针的引用:pt.Mv等同于(*pt).Mv。
和方法调用一样,若对以指针作为接收器的非接口方法,使用可寻址的值来引用,则(Go语言)将自动获取该值的地址:t.Mp等同于(&t).Mp。
|
|
尽管上面的例子使用了非接口类型,但从接口类型的值中创建一个方法值也是合法的。
|
|
Index expressions 索引表达式
若主表达式的形式是:
|
|
则表示可用x来检索的数组a、数组指针a、切片a、字符串a或映射a的元素,x分别被称为索引或映射键。以下规则适用:
如果a既不是映射也不是类型参数:
- 索引
x必须是一个无类型的常量,或者其核心类型必须是整数类型 - 常量索引必须是非负且可以用
int类型的值来表示 - 无类型常量索引会被赋予
int类型。 - 如果
0 <= x < len(a),则索引x在范围内,否则就超出了范围。
对于数组类型A的a:
对于数组类型指针的a:
a[x]是(*a)[x]的简写
对于切片类型S的a:
- 如果
x在运行时超出了范围,就会发生运行时恐慌 a[x]是索引x处的切片元素,a[x]的类型是S的元素类型。
For a of string type:
对于字符串类型的a:
对于映射类型为M的a:
对于参数类型为P的a:
- 索引表达式
a[x]必须对P的类型集中的所有类型的值有效。 P的类型集中所有类型的元素类型必须是相同的。在此上下文中,字符串类型的元素类型是byte。- 如果在
P的类型集中有一个映射类型,那么该类型集中的所有类型必须是映射类型,且对应的键类型必须都是一致的。 a[x]是索引为x的数组、切片或字符串元素,或者P实例化的类型实参中键为x的映射元素,a[x]的类型是(一致的)元素类型的类型。- 如果
P的类型集包括字符串类型,则a[x]不能再被赋值。
否则a[x]是非法的。
若将类型为map[K]V的映射a上的索引表达式使用在赋值语句或特殊格式的初始化中:
|
|
将产生一个额外的无类型布尔值。如果键x存在于映射中,ok的值为true,否则为false。
若给nil映射的元素赋值,将导致运行时恐慌。
Slice expressions 切片表达式
切片表达式从一个字符串、数组、数组指针或切片中构造一个子串或切片。有两种变体:一种是指定低位和高位边界的简单形式,另一种是同时也指定容量的完整形式。
Simple slice expressions 简单切片表达式
主表达式
|
|
构造了一个子字符串或切片。a的核心类型必须是字符串、数组、数组指针、切片或者bytestring。low和high所在的索引选择了哪些元素显示在操作数a的结果中。若结果的索引从0开始,则长度等于high 减去 low。在对数组a进行切片后
|
|
切片s有类型[]int,长度3,容量4,以及元素
|
|
为方便起见,任何索引都可以被省略。缺少的low索引默认为0;缺少的high索引默认为被切片的操作数的长度:
|
|
如果a是一个数组指针,则a[low:high]是(*a)[low:high]的简写。
对于数组或字符串,如果0 <= low <= high <= len(a),则索引在范围内,否则就超出了范围。对于切片,索引的上限是切片的容量cap(a),而不是长度。常量索引必须是非负的,并且可以用int类型的值来表示;对于数组或字符串常量,常量索引也必须在范围内。如果两个索引都是常量,它们必须满足low <= high。如果索引在运行时超出范围,就会发生运行时恐慌。
除了无类型字符串外:
-
如果被切片的操作数是字符串或切片,则切片的操作结果是一个与操作数相同类型的非常量值。
-
如果被切片的操作数是无类型的字符串,则切片的操作结果是一个
string类型的非常量值。 -
如果被切片的操作数是(必须可被寻址的)数组,则切片的操作结果是一个与数组的元素类型一致的切片。
如果有效切片表达式的切片操作数是nil切片,那么切片的操作结果就是一个nil切片。否则,如果切片的操作结果是一个切片,则它与操作数共享底层数组。
|
|
Full slice expressions 完整的切片表达式
主表达式
|
|
构造了一个与简单切片表达式a[low : high]相同类型的切片,并且具有相同的长度和元素。此外,它通过将结果切片设置为max 减去 low的容量。a的核心类型必须是数组,数组指针,或者切片(但不是字符串)。在对数组a进行切分后
|
|
切片t有类型[]int,长度2,容量4,以及元素
|
|
与简单切片表达式一样,如果a是一个数组指针,则a[low:high:max]是(*a)[low:high:max]的简写。如果切片的操作数是一个数组,它必须是可被寻址的。
如果0 <= low <= high <= max <= cap(a),则索引就在范围内,否则就超出了范围。常量索引必须是非负数,并且可以用int类型的值来表示;对于数组,常量索引也必须在范围内。如果多个索引是常量,那么出现的常量必须在相对于彼此的范围内。如果索引在运行时超出了范围,就会发生运行时恐慌。
Type assertions 类型断言
|
|
断言了x不是nil,并且x中存储的值是T类型。标记法x.(T)被称为类型断言。
更确切地说,如果T不是接口类型,则x.(T)断言x的动态类型与T的类型一致。在这种情况下,T必须实现x的(接口)类型;否则类型断言是无效的,因为对于x来说存储T类型的值是不可能的。如果T是一个接口类型,则x.(T) 断言x的动态类型实现了接口T。
If the type assertion holds, the value of the expression is the value stored in x and its type is T. If the type assertion is false, a run-time panic occurs. In other words, even though the dynamic type of x is known only at run time, the type of x.(T) is known to be T in a correct program.
如果类型断言成立,表达式的值就是存储在x中的值,其类型是T。 如果类型断言不成立,就会发生运行时恐慌。换句话说,尽管x的动态类型只有在运行时才知道,但在一个正确的程序中,x.(T)的类型是已知的,是T。=> 仍有疑问??
|
|
在赋值语句或特殊格式的初始化中使用的类型断言
|
|
将产生一个额外的无类型布尔值。如果断言成立,ok的值为true。否则为false,并且v的值是T类型的零值。在这种情况下不会发生运行时恐慌。
Calls 调用
|
|
带实参a1, a2, ... an调用了f。除了一种特殊情况以外,实参必须是可分配给F的参数类型的单值表达式,并且在函数被调用之前被求值。该表达式的类型是F的结果类型。方法调用是类似的,但是方法本身被指定为一个(在该方法的接收器类型的值上的)选择器。
|
|
如果f表示一个泛型函数,在它被调用或作为函数值使用之前,必须将其实例化。
在函数调用中,函数值和实参以通常的顺序被求值。在它们被求值之后,调用的参数被按值传递给函数,然后被调用的函数开始执行。当函数返回时,函数的返回参数按值传递给调用者。
调用一个nil的函数值会引起运行时恐慌。
作为一个特例,如果一个函数或方法的返回值g在数量上相等,并且可以单独分配给另一个函数或方法f的参数,那么调用f(g(parameters_of_g))将在把g的返回值依次绑定到f的参数后再调用f。对f的调用必须不包含对g的调用以外的参数,并且g必须至少有一个返回值。如果f有一个在最后的...参数,它将被分配给g的(在分配完普通参数后所剩余的)返回值。
|
|
如果x的方法集(x的类型)包含m,并且实参列表可以分配给m的参数列表,那么方法调用x.m()是有效的。如果x是可寻址的,并且&x的方法集包含m,则x.m()就是(&x).m()的简写:
|
|
没有明确的方法类型,也没有方法字面量。
Passing arguments to ... parameters 向…参数传递实参
如果f是带有一个...T类型的位置在最后的参数p的可变函数,那么在f内部,p的类型等同于[]T类型。如果f被调用时没有给p的实参,传递给p的值是nil。否则,传递的值是一个新的[]T类型的切片,这个切片带有一个新的底层数组,这个底层数组的连续元素作为实参,并且这些实参都必须可分配给T。因此,切片的长度和容量等于绑定到p的实参的数量,并且对每次调用(实参数量)都可能有所不同。
给出函数和调用
|
|
在Greeting函数第一次被调用时,who的值为nil,在第二次被调用时,who的值为[]string{"Joe", "Anna", "Eileen"}。
如果最后一个实参可以分配给切片类型[]T,并且后面是...,那么它就会在不改变值的情况下传递一个...T参数。在这种情况下,不会创建新的切片。
给出切片s并调用
|
|
在Greeting函数中,who将拥有与s相同的底层数组的值。
Instantiations 实例化
泛型函数或泛型是通过用类型实参替换类型参数而被实例化的。实例化分两步进行:
- 在泛型声明中,每个类型参数都被替换为其对应的类型实参。这种替换发生在整个函数或类型声明中,包括类型参数列表本身和该列表中的每个类型。
- 替换之后,每个类型实参必须实现相应类型参数的约束(若有需要则实例化它)。否则实例化就会失败。
实例化一个类型会产生一个新的非泛型的命名类型;实例化一个函数会产生一个新的非泛型的函数。
|
|
对于泛型函数,可以明确地提供类型实参,也可以靠部分或完整地推断出它们。非调用的泛型函数需要一个类型实参列表用于实例化;如果该列表是部分的,那么所有剩余的类型实参必须是可推断的。被调用的泛型函数可以提供一份(可能是部分的)类型实参列表,(如果省略的类型实参可以从普通(非类型)函数参数中推断出来)也可以完全省略。
|
|
部分类型实参列表不能是空的;至少第一个(类型)实参必须存在。该列表是完整的类型实参列表的前缀,剩下的参数需要推断。宽泛地说,类型实参可以从 “从右到左"省略。
|
|
对于泛型,所有的类型实参必须都被明确提供。
Type inference 类型推断
缺失的函数类型实参可以通过一系列的步骤来推断,如下所述。每个步骤都试图使用已知的信息来推断额外的类型实参。一旦所有的类型实参都是已知的,类型推断就会停止。在类型推断完成后,仍然有必要将所有类型实参替换为类型参数,并验证每个类型实参是否实现了相关的约束;推断的类型实参有可能无法实现约束,在这种情况下,实例化就会失败。
类型推断是基于:
- 类型参数列表
- 使用已知类型实参(如果有的话)初始化过的用于替换的映射
M - (可能是空的)普通函数实参列表(仅在函数调用的情况下)。
然后进行以下步骤:
如果没有普通函数实参或无类型函数实参数,则跳过相应的步骤。如果前一步没有推断出任何新的类型实参,则跳过约束类型推断,但如果有缺失的类型实参,则(这个步骤:即约束类型推断)至少要运行一次。
替换映射M贯穿所有的步骤,每个步骤都可以向M添加条目。一旦M为每个类型参数提供了一个类型实参或者推断步骤失败,这个过程就会停止。如果推断步骤失败,或者在最后一步之后M仍然缺少类型实参,则类型推断失败。
Type unification 类型联合
类型推断是基于类型联合的。单一的联合步骤适用于一个替换映射和两种类型,其中一个或两个可能是或包含类型参数。替换映射跟踪已知的(显式提供的或已经推断出的)类型实参:该映射包含每个类型参数P和相应的已知类型实参A的一个条目P→A。在联合过程中,已知的类型实参在比较类型时取代了它们对应的类型参数。联合过程是寻找使两个类型等同的替换映射条目的过程。
对于联合来说,如果两个类型不包含当前类型参数列表中的任何类型参数,或者它们是忽略了通道方向的通道类型,或者它们的底层类型是等同的,那么它们(这两个类型)就是一致的。
Unification works by comparing the structure of pairs of types: their structure disregarding type parameters must be identical, and types other than type parameters must be equivalent. A type parameter in one type may match any complete subtype in the other type; each successful match causes an entry to be added to the substitution map. If the structure differs, or types other than type parameters are not equivalent, unification fails.
联合是通过比较类型对的结构来实现的:它们的结构在不考虑类型参数时必须是一致的,而类型参数以外的类型必须是等同的。一个类型中的类型参数可以匹配另一个类型中的任何完整的子类型;每个成功的匹配都会将一个条目添加到替换映射中。如果结构不同,或者除类型参数外的其他类型不等同,那么联合就会失败。=> 仍有疑问??
For example, if T1 and T2 are type parameters, []map[int]bool can be unified with any of the following:
例如,如果T1和T2是类型参数,[]map[int]bool可以与以下任何一种类型联合:=> 仍有疑问??
|
|
On the other hand, []map[int]bool cannot be unified with any of
另一方面,[]map[int]bool不能与以下任何一个联合起来 => 仍有疑问??
|
|
作为这个通用规则的一个例外,由于定义类型D和类型字面量L从来都是不等同的,联合将D的底层类型与L进行比较。例如,给定定义类型
|
|
和类型字面量[]E,联合过程会将[]float64与[]E进行比较,并在替换映射中添加一个条目E→float64。
Function argument type inference 函数实参类型推断
Function argument type inference infers type arguments from function arguments: if a function parameter is declared with a type T that uses type parameters, unifying the type of the corresponding function argument with T may infer type arguments for the type parameters used by T.
函数实参类型推断从函数实参中推断出类型实参:如果函数参数声明时带有使用了类型参数的类型T,那么将对应函数实参的类型与T进行联合,可能推断出被T所使用的类型参数的类型实参。=>仍有疑问??
例如,给定泛型函数
|
|
和调用
|
|
Number的类型实参,可以通过联合vector的类型与对应的参数类型中推断出:[]float64和[]Number在结构上匹配,且float64与Number匹配。这就把Number→float64这个条目添加到替换映射中。在第一轮函数实参类型推断中,无类型实参,比如这里的第二个函数实参42,会被忽略,只有在还有未解决的类型参数时才会考虑。
推断发生在两个独立的阶段;每个阶段在一个特定的(参数,实参)对的列表上操作:
- 列表
Lt包含所有使用了类型参数的参数类型和有类型的函数实参所组成的(参数,实参)对。 - 列表
Lu包含所有剩下的参数类型为单一类型参数的对。在这个列表中,各自的函数实参是无类型的。
任何其他的(参数,实参)对都被忽略。
根据结构,列表Lu中对的实参是无类型的常量(或无类型的布尔比较结果)。而且由于无类型值的默认类型总是预先声明的非复合类型,它们永远不能与复合类型相匹配,所以仅考虑作为单一类型参数的参数类型就足够了。
每个列表都在一个独立的阶段中被处理:
- 在第一阶段,
Lt中的每各配对的参数和实参类型被联合。如果一个配对的联合成功了,它可能会产生新的条目,并被添加到替换映射M中。 - 第二阶段考虑列表
Lu中的条目。此阶段,将忽略已为其确定类型实参的类型参数。对于剩下的每一对,参数类型(这是一个单一的类型参数)和相应的无类型实参的默认类型进行联合。如果联合失败,则类型推断失败。
当联合过程成功时,即使所有的类型实参在最后一个列表元素被处理之前就被推断出来了,对每个列表的处理还是会继续进行,直到所有的列表元素都被考虑。
示例:
|
|
在例子min(1.0, 2)中,处理函数实参1.0会产生替换映射条目T → float64。因为处理过程一直持续到所有无类型的实参被考虑,所以报告了一个错误。这确保了类型推断不依赖于无类型实参的顺序。
Constraint type inference 约束类型推断
Constraint type inference infers type arguments by considering type constraints. If a type parameter P has a constraint with a core type C, unifying P with C may infer additional type arguments, either the type argument for P, or if that is already known, possibly the type arguments for type parameters used in C.
约束类型推断通过考虑类型约束来推断类型实参。如果类型参数P有一个核心类型C的约束,将P与C联合起来可能会推断出额外的类型实参,要么是P的类型实参,(如果这个是已知,则)要么可能是C中使用的类型参数的类型实参。=>仍有疑问??已知指的是什么,是 类型参数P有一个核心类型C的约束?
例如,考虑具有类型参数List和Elem的类型参数列表:
|
|
约束类型推断可以从List的类型实参推断出Elem的类型,因为Elem是List的核心类型[]Elem中的一个类型参数。如果类型实参是Bytes类型:
|
|
将Bytes的底层类型与核心类型联合起来,就意味着将[]byte与[]Elem联合起来。这一联合成功了,并产生了Elem→byte的替换映射条目。因此,在这个例子中,约束类型推断可以从第一个类型实参推断出第二个类型实参。
Using the core type of a constraint may lose some information: In the (unlikely) case that the constraint’s type set contains a single defined type N, the corresponding core type is N’s underlying type rather than N itself. In this case, constraint type inference may succeed but instantiation will fail because the inferred type is not in the type set of the constraint. Thus, constraint type inference uses the adjusted core type of a constraint: if the type set contains a single type, use that type; otherwise use the constraint’s core type.
使用约束的核心类型可能会丢失一些信息。在(不太可能的)情况下,约束的类型集包含单一的定义类型N,相应的核心类型是N的底层类型而不是N本身。在这种情况下,约束的类型推断可能会成功,但实例化会失败,因为推断的类型不在约束的类型集中。因此,约束类型推断使用调整后的约束的核心类型:如果类型集包含一个单一的类型,则使用该类型;否则使用约束的核心类型。=> 仍有疑问??
通常,约束类型推断分两个阶段进行。从一个给定的替换映射M开始
- 对于所有带调整过的核心类型的类型参数,将该类型参数与该类型联合起来。如果任何联合失败,约束类型推断就会失败。
- 此时,
M中的一些条目可能将类型参数映射到其他类型参数或包含类型参数的类型。对于M中每个条目P→A,其中A是或包含类型参数Q,而M中存在条目Q→B,用A中相应的B替换这些Q。在无法进一步替换时,则停止。
约束类型推断的结果是从类型参数P到类型实参A的最终替换映射M,其中在任何A中都没有出现类型参数P。
例如,给定类型参数列表
|
|
以及为类型参数A提供的单一类型实参int,初始替换映射M包含条目A→int。
在第一阶段,类型参数B和C与它们各自约束的核心类型联合起来。这就在M中加入了B→[]C和C→*A的条目。
此时,M中存在两个条目,其右手边是或包含类型参数,而M中存在其他条目:[]C和*A。在第二阶段,这些类型参数被替换成它们各自的类型。这发生在哪个顺序上并不重要。从第一阶段后的M的状态开始:
A` → `int`, `B` → `[]C`, `C` → `*A
用int替换→右边的A。
A` → `int`, `B` → `[]C`, `C` → `*int
用*int替换→右边的C。
A` → `int`, `B` → `[]*int`, `C` → `*int
此时,不可能再进一步替换,该替换映射已满。因此,M代表类型参数到类型实参列表的最终映射。
Operators 操作符
操作符将操作数组合成表达式。
Expression = UnaryExpr | Expression binary_op Expression .
UnaryExpr = PrimaryExpr | unary_op UnaryExpr .
binary_op = "||" | "&&" | rel_op | add_op | mul_op .
rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" .
add_op = "+" | "-" | "|" | "^" .
mul_op = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" .
unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
比较操作符将在其他地方讨论。对于其他二元运算符,操作数类型必须是一致的,除非操作涉及移位或无类型的常量。对于只涉及常量的操作,请参见常量表达式部分。
除了移位操作之外,如果一个操作数是无类型常量,而另一个操作数不是,那么该常量将被隐式地转换为另一个操作数的类型。
移位表达式中的右操作数必须是整数类型,或者是可以用uint类型的值表示的无类型常量。如果一个非常量移位表达式的左操作数是一个无类型常量,那么它首先被隐式地转换为假设移位表达式被其左操作数单独替换时的类型。
|
|
=> 仍有疑问??
Operator precedence 优先级运算符
一元运算符的优先级最高。由于++和--运算符构成的是语句,而不是表达式,因此它们不属于运算符等级体系。因此,语句*p++与(*p)++相同。
二元运算符有五个优先级别。乘法运算符绑定最强,其次是加法运算符、比较运算符、&&(逻辑AND),最后是||(逻辑OR)。
|
|
优先级相同的二元运算符按从左到右的顺序结合。例如,x / y * z等同于(x / y)* z。
|
|
Arithmetic operators 算术运算符
算术运算符适用于数字值,产生的结果与第一个操作数的类型相同。四个标准的算术运算符(+、-、*、/)适用于整型、浮点型和复数型;+也适用于字符串。位逻辑运算符和移位运算符只适用于整型。
+ sum (和) integers, floats, complex values, strings
- difference (差) integers, floats, complex values
* product (积) integers, floats, complex values
/ quotient (商) integers, floats, complex values
% remainder (余) integers
& bitwise AND integers
| bitwise OR integers
^ bitwise XOR integers
&^ bit clear (AND NOT) integers
<< left shift integer << integer >= 0
>> right shift integer >> integer >= 0
如果操作数类型是类型参数,那么操作数必须适用于该类型集中的每个类型。操作数被表示为类型参数被实例化的类型实参的值,并且操作以该类型实参的精度进行计算。例如,给定一个函数:
|
|
x * y的乘积 和 s += x * y的加法分别以float32或float64精度计算,这取决于F的类型实参。
Integer operators 整数运算符
对于两个整数值x和y,它们的整数商q = x / y和余数r = x % y满足以下关系:
x = q*y + r and |r| < |y|
with x / y被截断到零("截断除法")。
x y x / y x % y
5 3 1 2
-5 3 -1 -2
5 -3 -1 2
-5 -3 1 -2
这条规则有一个例外:如果)被除数(dividendx是x的int类型的最负值,那么商q = x / -1就等于x(而r = 0),这是由于二元补码的整数溢出:
x, q
int8 -128
int16 -32768
int32 -2147483648
int64 -9223372036854775808
如果除数(divisor)是一个常量,那么它一定不能为零。如果除数在运行时为零,就会发生运行时恐慌。如果除数是非负数,并且除数是2的常数幂,除法可以用右移来代替,计算余数可以用按位与操作来代替。
x x / 4 x % 4 x >> 2 x & 3
11 2 3 2 3
-11 -2 -3 -3 1
移位运算符通过右操作数指定的移位计数对左操作数进行移位,移位计数必须为非负数。如果移位计数在运行时为负数,就会发生运行时恐慌。如果左操作数是有符号整数,移位操作符实现算术移位;如果是无符号整数,则实现逻辑移位。移位计数没有上限。移位计数为n的移位行为就像左操作数被1移了n次。因此,x<<1与x*2相同,x>>1与x/2相同(但向右移位被截断到负无穷大)。
对于整数操作数,一元运算符+、-和^的定义如下:
+x is 0 + x
-x negation is 0 - x
^x bitwise complement is m ^ x with m = "all bits set to 1" for unsigned x
and m = -1 for signed x
Integer overflow 整数溢出
对于无符号整型值,+、-、*和<<运算是以2n为模来计算的,其中n是无符号整型的位宽。广义上讲,这些无符号整型操作在溢出时丢弃高位,程序可以依靠 “wrap around"。
对于有符号整型值,+、-、*、/和<<运算可以合法地溢出,其产生的值是存在的,并且可以被有符号整型表示法、其操作和操作数明确地定义。溢出不会引起运行时恐慌。在假设不发生溢出的情况下,编译器可能不会优化代码。例如,它不会假设x<x+1总是真的。
Floating-point operators 浮点运算符
对于浮点数和复数,+x与x相同,而-x是负的x。浮点数或复数除以0的结果,在IEEE-754标准中没有规定;是否会发生运行时恐慌是由具体实现决定的。
An implementation may combine multiple floating-point operations into a single fused operation, possibly across statements, and produce a result that differs from the value obtained by executing and rounding the instructions individually. An explicit floating-point type conversion rounds to the precision of the target type, preventing fusion that would discard that rounding.
某些实现可能会将多个浮点运算合并为一个单一的融合运算,可能会跨越语句,产生的结果与单独执行和舍入指令得到的值不同。明确的浮点类型转换是按照目标类型的精度进行舍入的,这样就可以避免融合时放弃舍入的做法。=> 仍有疑问??
例如,一些体系架构提供了一个 “fused multiply and add"(FMA)指令,其在计算x*y+z时,不对中间结果x*y进行舍入。这些例子显示了Go的实现何时可以使用该指令:
|
|
String concatenation 字符串连接
字符串可以使用+运算符或+=赋值运算符进行连接:
s := "hi" + string(c)
s += " and good bye"
字符串加法通过连接操作数创建一个新的字符串。
Comparison operators 比较运算符
比较运算符比较两个操作数,并产生一个无类型布尔值。
== equal
!= not equal
< less
<= less or equal
> greater
>= greater or equal
在任何比较中,第一个操作数必须是可分配给第二个操作数的类型,反之亦然。
相等运算符==和!=适用于可比较的操作数。排序运算符<, <=, >, 和>=适用于被排序的操作数。这些术语和比较结果的定义如下:
- 布尔值是可比较的。如果两个布尔值都是
true或者都是false,那么它们是相等的。 - 按照通常的方式,整数值是可比较的并且是可排序的。
- 按照IEEE-754标准的定义,浮点值是可比较的并且是可排序的。
- 复数值是可比较的。如果
real(u) == real(v)和imag(u) == imag(v),则这两个复数值u和v是相等的。 - 字符串值是可(按字节顺序)比较的并且是可(按字节顺序)排序的。
- 指针值是可比较的。如果两个指针值指向同一个变量,或者两个指针值都是
nil,则它们的值是相等的。指向不同的零尺寸变量的指针值可能相等,也可能不相等。 - 通道值是可比较的。如果两个通道是由同一个调用make创建的,或者它们的值都为
nil,则它们的值是相等的。 - 接口值是可比较的。如果两个接口值有一致的动态类型和相同的动态值,或者两者的值都是
nil,则它们的值是相等的。 - 非接口类型
X的值x和接口类型T的值t,在X类型的值是可比较的并且X实现T时是可比较的。如果t的动态类型等于X,且t的动态值等于x,则它们是相等的。 - 如果结构体值的所有字段都是可比较的,那么结构体值就是可比较的。如果两个结构体值对应的非空白字段相等,那么它们就是相等的。
- 如果数组元素类型的值是可比较的,那么数组值是可比较的。如果两个数组的对应元素是相等的,那么这两个数组值就是相等的。
对两个动态类型相同的接口值进行比较,如果它们的类型值不具有可比性,则会引起运行时恐慌。这种行为不仅适用于直接的接口值比较,也适用于比较接口值的数组或带有接口值字段的结构体。
切片值、映射值和函数值是不可比较的。然而,作为一种特殊情况,切片值、映射值或函数值可以与预先声明的标识符nil比较。指针值、通道值和接口值与nil的比较也是允许的,并遵循上述的通用规则。
|
|
Logical operators 逻辑运算符
逻辑运算符适用于布尔值,并产生一个与操作数相同类型的结果。右操作数是按条件进行求值的。
&& conditional AND p && q is "if p then q else false"
|| conditional OR p || q is "if p then true else q"
! NOT !p is "not p"
Address operators 地址运算符
对于类型为T的操作数x,寻址操作&x产生一个类型为*T的指针指向x。该操作数x必须是可寻址的,也就是说,它要么是一个变量、指针间接(pointer indirection)或对切片的索引操作(slice indexing operation,是一个名词);要么是一个可寻址结构体操作数的字段选择器;要么是一个可寻址数组的数组索引操作。作为可寻址要求的一个例外,x也可以是一个(可能是括号内的)复合字面量。如果对x的求值会引起运行时恐慌,那么对&x的求值也会引起运行时恐慌。
对于指针类型*T的操作数x,指针间接*x表示x所指向的T类型的变量,如果x是nil,试图求值*x将导致运行时恐慌。
|
|
Receive operator 接收操作符
对于核心类型为通道的操作数ch,接收操作<-ch的值是从通道ch中接收的值,通道方向必须允许接收操作,接收操作的类型是通道的元素类型。这个表达式会阻塞,直到有一个可用的值。从一个 nil的通道接收时,将永远阻塞。在一个已经关闭的通道上的接收操作总是可以立即进行,并在任何先前发送的值被接收后,产生一个该元素类型的零值。
|
|
在赋值语句或特殊形式的初始化中使用的一个接收表达式
|
|
将产生一个额外的无类型布尔值结果,报告通信是否成功。如果收到的值是由一个成功的发送操作传递给通道的,那么ok的值为true,如果是一个因为通道关闭且空而产生的零值,则为false。
Conversions 转换
转换将表达式的类型改变为转换所指定的类型。转换可以出现在源文件中的字面量上,也可以隐含在由表达式所在的上下文。
显式转换是T(x)形式的表达式,其中T是一个类型,x是可以被转换为T类型的表达式。
Conversion = Type "(" Expression [ "," ] ")" .
如果类型以运算符*或<-开头,或者如果类型以关键字func开头,并且没有结果列表,那么在必要时必须用圆括号括起来,以避免产生歧义:
|
|
一个常量值x可以被转换为T类型,如果x可以用T的一个值来表示的话。作为一种特殊情况,可以使用 与 非常量x相同的规则显式地将整数常量x转换为字符串类型。
将常量转换为非类型参数的类型,会得到一个有类型的常量。
|
|
将常量转换为一个类型参数会产生一个该类型的非常量值,该值表示为类型参数实例化时所带的类型实参的值。例如,给定一个函数:
func f[P ~float32|~float64]() {
… P(1.1) …
}
转换P(1.1)的结果是一个P类型的非常量值,而值1.1被表示为float32或float64,这取决于f的类型参数。因此,如果f被实例化为float32类型,那么表达式P(1.1)+1.2的数值会用与非常量float32加法相同的精度进行计算。
非常量值x可以在以下的任何情况下被转换为T类型:
x可以被分配给T。- 忽略结构体标签(见下文),
x的类型和T不是类型参数,但有一致的底层类型。 - 忽略结构体标签(见下文),
x的类型和T是指针类型,不是命名类型,它们的指针基类型不是类型参数,但有一致的底层类型。 x的类型和T都是整型或浮点型。x的类型和T都是复数类型。x是一个整型、字节型、符文型的切片,T是一个字符串类型。x是一个字符串类型,T是一个字节型、符文型的切片。x是一个切片,T是一个指向数组的指针,而且切片和数组的类型有一致的元素类型。
此外,如果T或x的类型V是类型参数,如果满足以下条件之一,x也可以被转换为T类型:
V和T都是类型参数,并且V的类型集中的每个类型的值都可以转换为T的类型集中的每个类型。- 只有
V是一个类型参数,并且V的类型集中的每个类型的值都可以转换为T。 - 只有
T是一个类型参数,并且x可以转换为T的类型集中的每个类型。
为了转换的目的,在比较结构体类型的是否一致时,结构体标签被忽略:
|
|
数值类型之间或与字符串类型之间的(非常量)转换有特殊的规则。这些转换可能会改变x的表示,并产生运行时间成本。所有其他的转换只改变x的类型而不改变其表示。
没有语言机制可以在指针和整型之间进行转换。unsafe包在受限制的情况下实现了这个功能。
Conversions between numeric types 数值型之间的转换
对于非常量数值的转换,适用以下规则:
- 当在整型之间转换时,如果数值是有符号的整型,那么它被符号位扩展到隐式的无限精度;否则它被零扩展。然后,它被截断以适应结果类型的大小。例如,如果
v := uint16(0x10F0),那么uint32(int8(v)) == 0xFFFFFFF0。该转换总是产生一个有效的值;没有溢出的迹象。 - 当把浮点型数值转换为整型时,小数会被丢弃(向零截断)。
- 当将一个整型或浮点型数值转换为浮点型,或将一个复数型数值转换为另一个复数类型时,结果值被舍入到目标类型所指定的精度。例如,
float32类型的变量x的值可能会使用超出IEEE-754 32位数的额外精度来存储,但是float32(x)表示将x的值舍入到32位精度的结果。同样地,x + 0.1可能使用超过32位的精度,但是float32(x + 0.1)则不会。
在所有涉及浮点值或复数值的非常量转换中,如果结果类型不能表示该值,转换仍会成功,但结果值取决于实现。
Conversions to and from a string type 与字符串类型的转换
-
将有符号或无符号的整型值转换为字符串类型,会产生一个包含该整型值的UTF-8表示的字符串。在有效的Unicode码点范围之外的值会被转换为
"\uFFFD"。1 2 3 4 5 6string('a') // "a" string(-1) // "\ufffd" == "\xef\xbf\xbd" string(0xf8) // "\u00f8" == "ø" == "\xc3\xb8" type myString string myString(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5" -
将字节切片转换为字符串类型,可以得到一个字符串,其连续的字节是该切片的元素。
1 2 3 4 5 6 7 8 9 10string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}) // "hellø" string([]byte{}) // "" string([]byte(nil)) // "" type bytes []byte string(bytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'}) // "hellø" type myByte byte string([]myByte{'w', 'o', 'r', 'l', 'd', '!'}) // "world!" myString([]myByte{'\xf0', '\x9f', '\x8c', '\x8d'}) // "🌍" -
将符文切片转换为字符串类型,可以得到一个字符串,即转换为字符串的各个符文值的连接。
1 2 3 4 5 6 7 8 9 10string([]rune{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" string([]rune{}) // "" string([]rune(nil)) // "" type runes []rune string(runes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" type myRune rune string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬" myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎" -
将字符串类型的值转换为字节类型的切片,得到一个切片,其连续的元素是字符串的字节。
1 2 3 4 5 6 7[]byte("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'} []byte("") // []byte{} bytes("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'} []myByte("world!") // []myByte{'w', 'o', 'r', 'l', 'd', '!'} []myByte(myString("🌏")) // []myByte{'\xf0', '\x9f', '\x8c', '\x8f'} -
将字符串类型的值转换为符文类型的切片,会得到一个包含该字符串的各个Unicode码点的切片。
1 2 3 4 5 6 7[]rune(myString("白鵬翔")) // []rune{0x767d, 0x9d6c, 0x7fd4} []rune("") // []rune{} runes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4} []myRune("♫♬") // []myRune{0x266b, 0x266c} []myRune(myString("🌐")) // []myRune{0x1f310}
Conversions from slice to array pointer 从切片到数组指针的转换
将切片转换为数组指针,会得到一个指向切片底层数组的指针。如果切片的长度小于数组的长度,就会发生运行时恐慌。
|
|
Constant expressions 常量表达式
常量表达式可以只包含常量操作数,并在编译时进行求值。
无类型的布尔、数值和字符串常量可以作为操作数使用,只要合法地分别使用布尔、数值或字符串类型的操作数。
常量比较总是产生一个无类型的布尔常量。如果常量移位表达式的左操作数是一个无类型的常量,那么结果就是一个整型常量;否则就是一个与左操作数相同类型的常量(左操作数必须是整型)。
任何其他对无类型常量的操作都会产生一个相同类型的无类型常量,也就是布尔、整数、浮点、复数或字符串常量。如果一个二元运算(除移位外)的无类型操作数是不同种类的,那么结果就是出现在如下列表的操作数类型:整数,符文,浮点,复数。例如,一个无类型的整数常量除以一个无类型的复数常量,得到一个无类型的复数常量。
|
|
将内置函数 complex 应用于无类型的整数、符文或浮点常量,可以得到一个无类型的复数常量。
|
|
常量表达式总是被精确地求值;中间值和常量本身可能需要比语言中任何预先声明的类型所支持的精度大得多。以下是合法的声明:
|
|
常量除法或取余操作的除数一定不能为零。
|
|
类型常量的值必须总是可以准确地由常量类型的值来表示。下面的常量表达式是非法的:
|
|
一元按位补运算符^使用的掩码符合非常量的规则:对于无符号常量来说是所有(掩码)位都是1,对于有符号和无类型的常量来说是-1。=> 仍有疑问??
|
|
实现限制:编译器在计算无类型浮点或复数常量表达式时可能会使用舍入,请参见常量部分的实现限制。这种舍入可能会导致浮点常量表达式在整数上下文中无效,即使它在使用无限精度计算时是整数,反之亦然。
Order of evaluation 求值顺序
在包级别上,初始化依赖关系决定了变量声明中各个初始化表达式的求值顺序。除此之外,在求值表达式、赋值或返回语句的操作数时,所有的函数调用、方法调用和通信操作都是按词法从左到右的顺序求值的。
例如,在(函数局部)赋值中
|
|
函数调用和通信发生的顺序是f(), h(), i(), j(), <-c, g(), 和k()。然而,与x的求值和索引以及y的求值相比,这些事件的顺序没有被指定。
|
|
在包级别上,对于独立的初始化表达式来说,初始化依赖关系会覆盖其从左到右的求值规则,但不覆盖每个表达式中的操作数:
|
|
函数调用按照u()、sqr()、v()、f()、v()、g()的顺序发生。
单个表达式中的浮点运算是按照运算符的结合性来求值的。显式的括号会通过覆盖默认的结合性来影响求值。在表达式x + (y + z)中,加法y + z会在加x之前进行。
1.1.12 - 语句
Statements 语句
语句控制执行。
Statement =
Declaration | LabeledStmt | SimpleStmt |
GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
DeferStmt .
SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
Terminating statements 终止语句
终止语句中断了一个块中的常规控制流。下列语句是终止性的:
- “
return“或 “goto“语句。 - 对内置函数
panic的调用。 - 语句列表以终止语句结束的块。
- 一个 “
if“语句,其中:- 存在 “
else“分支,并且 - 两个分支都是终止语句。
- 存在 “
- 一个 “
for“语句,其中:- 没有 “
break“语句引用”for“语句,并且 - 循环条件不存在,并且
- 这个”
for“语句没有使用range子句。
- 没有 “
- 一个 “
switch“语句,其中:- 没有 “
break“语句引用 “switch“语句 - 有一个默认的分支,并且
- 每个分支下的语句列表,包括默认分支,都以一个终止语句结束,或者是一个可能标有 “fallthrough “的语句。
- 没有 “
- 一个 “
select“语句,其中:- 没有”
break“语句引用”select“语句,并且 - 每个分支下的语句列表,包括默认分支(如果存在),都以一个终止语句结束
- 没有”
- 标记终止语句的标签语句。
所有其他语句都不是终止性的。
如果语句列表不是空的,并且其最后的非空语句是终止性的,则该列表以终止性语句结束。
Empty statements 空语句
空语句不做任何事情。
EmptyStmt = .
Labeled statements 标签语句
标签语句可以是goto、break或continue语句的目标。
LabeledStmt = Label ":" Statement .
Label = identifier .
Error: log.Panic("error encountered")
Expression statements 表达式语句
除了特定的内置函数外,函数和方法调用以及接收操作可以出现在语句上下文中。这样的语句可以用圆括号括起来。
ExpressionStmt = Expression .
以下内置函数不允许出现在语句上下文中:
|
|
|
|
Send statements 发送语句
发送语句在通道上发送一个值。通道表达式的核心类型必须是一个通道,通道方向必须允许发送操作,而且要发送的值的类型必须是可以分配给通道的元素类型。
SendStmt = Channel "<-" Expression .
Channel = Expression .
在通信开始之前,通道和值表达式都被求值。通信阻塞,直到发送(操作)可以进行。如果有接收端准备好了,那么在一个没有缓冲的通道上的发送可以继续进行。在缓冲通道上的发送可以在缓冲区有空间的情况下进行。在关闭的通道上进行发送会引起运行时恐慌。在nil通道上的发送会永远阻塞。
|
|
IncDec statements 自增自减语句
++和--语句通过无类型常量1来增加或减少其操作数。与赋值一样,操作数必须是可寻址的,或者是一个映射索引表达式。
IncDecStmt = Expression ( "++" | "--" ) .
下面的赋值语句在语义上是等同的:
IncDec statement Assignment
x++ x += 1
x-- x -= 1
Assignment statements 赋值语句
赋值是用一个表达式指定的新值来替换存储在变量中的当前值。赋值语句可以为单个变量赋值,也可以将多个值赋给匹配数量的变量。
Assignment = ExpressionList assign_op ExpressionList .
assign_op = [ add_op | mul_op ] "=" .
每个左操作数必须是可寻址的,或是一个映射索引表达式,或是(仅对=赋值)空白标识符,即_。操作数可以用圆括号括起来。
|
|
赋值操作x op= y,其中op是一个二元算术运算符,相当于x = x op (y),但只对x进行一次求值。op=结构是一个单一的标记。在赋值操作中,左表达式和右表达式列表都必须正好包含一个单值表达式,并且左表达式不能是空白标识符。
|
|
多元赋值将多值运算的各个元素分配给一个变量列表。有两种形式。在第一种形式中,右操作数是单个多值表达式,如一个函数调用、一个通道或映射操作,或一个类型断言。左操作数必须与值的数量相匹配。例如,如果f是一个返回两个值的函数,
|
|
将第一个值赋给 x,将第二个值赋给 y。在第二种形式中,左操作数必须等于右表达式数量,每个表达式必须是单值的,右边的第n个表达式被分配给左边的第n个操作数:
|
|
空白标识符,即_提供了一种在赋值中忽略右值的方法:
|
|
赋值分两个阶段进行。第一阶段,左边的索引表达式和指针间接(包括选择器中的隐式指针间接)的操作数以及右边的表达式都按照通常的顺序被求值。第二阶段,赋值是按照从左到右的顺序进行的。
|
|
在赋值中,每个值必须可以赋给它所赋的操作数的类型,但有以下特殊情况:
- 任何类型的值都可以被分配给
空白标识符。 - 如果无类型的常量被分配给接口类型的变量或空白标识符,那么该常量首先被隐式地转换为其默认类型。
- 如果无类型的布尔值被分配给接口类型的变量或空白标识符,它首先被隐式转换为
bool。
If statements - if 语句
“if “语句根据布尔表达式的值指定两个分支的条件性执行。如果表达式的值为真,则执行 “if “分支,否则,执行 “else “分支(如果存在)。
IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
if x > max {
x = max
}
表达式前面可以有一个简单的语句,它在表达式被求值之前执行。
|
|
Switch statements - switch 语句
“switch “语句提供多路执行。表达式或类型与 “switch “内部的 “case “进行比较,以确定执行哪个分支。
SwitchStmt = ExprSwitchStmt | TypeSwitchStmt .
有两种形式:表达式开关和类型开关。在表达式开关中,case 包含与开关表达式的值进行比较的表达式。在类型开关中,case 包含类型,这些类型与特别说明的表达式开关的类型进行比较。在switch语句中,switch 表达式被精确地求值一次。
Expression switches 表达式开关
在表达式开关中,switch 表达式被求值,case表达式(不需要是常量)被从左到右和从上到下求值;第一个等于switch表达式的表达式会触发相关case语句的执行;其他case被跳过。如果没有匹配的case,但有一个 “default” case,那么这个语句将被执行。“default” case 最多只能有一个,它可以出现在 “switch “语句的任何地方。缺省的switch 表达式等同于布尔值true。
ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
ExprCaseClause = ExprSwitchCase ":" StatementList .
ExprSwitchCase = "case" ExpressionList | "default" .
如果switch 表达式求值为无类型的常量,它首先被隐式地转换为其默认类型。预先声明的无类型值nil不能作为switch 表达式使用。switch 表达式的类型必须是可比较的。
如果一个case 表达式是无类型的,它首先被隐式地转换为switch 表达式的类型。对于每个(可能转换过的)case 表达式x和switch 表达式的值t,x == t必须是一个有效的比较。
换句话说,switch 表达式被当作是用来声明和初始化一个没有明确类型的临时变量t;每个case表达式x都是用t的值来测试是否相等。
在case或default子句中,最后一个非空语句可以是一个(可能被标记的)“fallthrough “语句,表示控制应该从这个子句的结尾流向下一个子句的第一个语句。否则,控制将流向 “switch “语句的末尾。“fallthrough"语句可以作为表达式开关中除最后一个子句之外的所有子句的最后一个语句出现。
switch 表达式前面可以有一个简单的语句,它在表达式被求值之前执行。
|
|
实现限制:编译器可能不允许多个case 表达式求值为同一个常量。例如,目前的编译器不允许在case表达式中出现重复的整型常量、浮点常量或字符串常量。
Type switches 类型开关
类型开关比较的是类型而不是值。它与表达式开关类似。它由一个特殊的switch 表达式标记,该表达式具有类型断言的形式,使用关键字type而不是实际的类型:
|
|
然后,case 将实际类型T与表达式x的动态类型相匹配。与类型断言一样,x必须是接口类型,但不是类型参数,而且case 中列出的每个非接口类型T必须实现x的类型。在类型开关的case 中,列出的类型都必须是不同的。
TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
TypeCaseClause = TypeSwitchCase ":" StatementList .
TypeSwitchCase = "case" TypeList | "default" .
TypeSwitchGuard 可能包括一个短变量声明。当使用这种形式时,该变量在每个子句的隐含块中的TypeSwitchCase的末尾被声明。在子句中,如果case正好列出了一种类型,那么变量就有这种类型;否则,变量就有TypeSwitchGuard中表达式的类型。
case 可以使用预先声明的标识符nil来代替类型;当TypeSwitchGuard中的表达式是一个nil接口值时,该case被选中。最多只能有一个nil case。
给定一个interface{}类型的表达式x,下面的类型开关:
|
|
可以重写:
|
|
类型参数或泛型可以作为 case 中的一个类型。如果在实例化时,该类型被发现与开关中的另一个条目重复,则选择第一个匹配的case。
|
|
类型开关防护(guard )前可以有一个简单的语句,该语句在防护(guard )被求值前执行。
在类型开关中不允许使用 “fallthrough “语句。
For statements - for 语句
“for “语句指定重复执行一个块。有三种形式:迭代可以由单个条件、“for “子句或 “range “子句控制。
ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
Condition = Expression .
For statements with single condition 带有单一条件的for语句
在其最简单的形式中,“for “语句指定重复执行一个块,只要一个布尔条件被求值为真。该条件在每次迭代前被求值。如果条件不存在,它就等同于布尔值true。
|
|
For statements with for clause 带有for子句的for语句
带有for子句的 “for “语句也受其条件的控制,但另外它可以指定一个init和一个post语句,如一个赋值,一个增量或减量语句。init语句可以是一个短变量声明,但post语句则不能。由init语句声明的变量会在每次迭代中重复使用。
ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
InitStmt = SimpleStmt .
PostStmt = SimpleStmt .
for i := 0; i < 10; i++ {
f(i)
}
如果(init语句)非空,则它在求值第一个迭代的条件之前被执行一次;post语句在每次执行块之后被执行(而且只有当该块被执行时)。For子句的任何元素都可以是空的,但是(除非只有一个条件)分号是必须的。如果没有条件,则等同于布尔值true。=> 仍有疑问??
for cond { S() } is the same as for ; cond ; { S() }
for { S() } is the same as for true { S() }
For statements with range clause 带有range子句的for语句
带有 “range“子句的 “for “语句遍历一个数组、切片、字符串或映射的所有条目,或在一个通道上收到的值。对于每个条目,如果存在的话,它将迭代值分配给相应的迭代变量,然后执行该块。
RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
在 “range“子句中右边的表达式称为范围表达式,其核心类型必须是数组、指向数组的指针、切片、字符串、映射或允许接收操作的通道。和赋值一样,如果左操作数存在的话,那么它必须是可寻址的或映射索引表达式;它们(即左操作数)表示迭代变量。如果range 表达式是一个通道,最多允许一个迭代变量,其他情况下最多可以有两个迭代变量。如果最后一个迭代变量是空白标识符,即_,那么range 子句就等同于没有该空白标识符的相同子句。
在开始循环之前,range 表达式x被求值一次,但有一个例外:如果最多只有一个迭代变量,并且len(x)是常量,那么range 表达式不被求值。
Function calls on the left are evaluated once per iteration. For each iteration, iteration values are produced as follows if the respective iteration variables are present:
左边的函数调用在每个迭代中被求值一次(=>仍有疑问??)。对于每个迭代,如果各自的迭代变量存在,则迭代值按以下产生:
Range expression 1st value 2nd value
range 表达式 第一个值 第二
array or slice a [n]E, *[n]E, or []E index i int a[i] E
string s string type index i int see below rune
map m map[K]V key k K m[k] V
channel c chan E, <-chan E element e E
- 对于一个数组值、数组指针值或切片值
a,索引迭代值按递增顺序产生,从元素索引0开始。如果最多只有一个迭代变量,range 循环产生从0到len(a)-1的迭代值,并且不对数组或切片本身进行索引。对于一个nil切片,迭代次数为0。 - 对于一个字符串值,“range “子句在字符串中的Unicode码点上进行迭代,从字节索引0开始。在连续的迭代中,索引值将是字符串中连续的UTF-8编码码点的第一个字节的索引,第二个值,类型为
rune,将是相应码点的值。如果迭代遇到一个无效的UTF-8序列,第二个值将是(Unicode替换字符)0xFFFD,下一次迭代将在字符串中推进一个字节。 - 对映射的迭代顺序没有指定,不保证每次迭代都是一样的。如果在迭代过程中删除了一个尚未到达的映射条目,将不会产生相应的迭代值。如果在迭代过程中创建了一个映射条目,该条目可能在迭代过程中被产生,也可能被跳过。对于每个创建的条目,以及从一个迭代到另一个迭代,选择可能有所不同。如果映射为
nil,迭代次数为0。 - 对于通道,产生的迭代值是通道上连续发送的值,直到通道关闭。如果通道为
nil,则 range 表达式永远阻塞。
迭代值被分配给各自的迭代变量,就像在赋值语句中一样。
迭代变量可以由 “range “子句使用短变量声明的形式(:=)来声明。在这种情况下,它们的类型被设置为各自的迭代值的类型,它们的作用域是 “for “语句的块;它们在每个迭代中被重复使用。如果迭代变量是在 “for “语句之外声明的,执行后它们的值将是最后一次迭代的值。
|
|
Go statements - go 语句
go语句作为一个独立的并发控制线程(或称为goroutine),在同一地址空间内开始执行一个函数调用。
GoStmt = "go" Expression .
(go语句中的)表达式必须是一个函数或方法调用;其不能用圆括号括起来。对内置函数的调用与表达式语句一样受到限制。
函数值和参数在调用的goroutine中像往常一样被求值,但与普通调用不同的是,程序执行不会等待被调用的函数完成。相反,该函数开始在一个新的goroutine中独立执行。当函数终止时,其goroutine也会终止。如果该函数有任何返回值,当函数完成时,它们会被丢弃。
|
|
Select statements - select 语句
“select “语句选择一组可能的发送或接收操作中的一个来进行。它看起来类似于 “switch “语句,但其 case 都是只涉及通信操作。
SelectStmt = "select" "{" { CommClause } "}" .
CommClause = CommCase ":" StatementList .
CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
RecvStmt = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
RecvExpr = Expression .
一个有 RecvStmt 的 case 可以将 RecvExpr 的结果分配给一个或两个变量,这些变量可以用短变量声明来声明。RecvExpr 必须是一个(可能是圆括号内的)接收操作。最多可以有一个default case,它可以出现在 case 列表的任何地方。
“select “语句的执行分几个步骤进行:
- 对于语句中的所有情况,在进入 “
select“语句时,接收操作的通道操作数、通道、发送语句的右侧表达式(按源代码出现的顺序)被求值一次。结果是一组要接收或发送的通道,以及对应的要发送的值。无论选择哪一个(如果有)通信操作来进行,在这次求值中的任何副作用都会发生。在 RecvStmt 左侧的表达式有一个短变量声明或赋值,还没有被求值。 - 如果一个或多个通信可以进行,则通过统一的伪随机选择来选择一个可以进行的通信。否则,如果有一个default case,就会选择该情况。如果没有default case,"
select“语句就会阻塞,直到至少有一项通信可以进行。 - 除非选择的情况是default case,否则将执行相应的通信操作。
- 如果选择的 case 是一个带有短变量声明或赋值的RecvStmt,左边的表达式会被求值,接收到的值(或多个值)被用于赋值。
- 所选 case 语句列表被执行。
由于在nil通道上的通信永远不能进行,所以只有nil通道且没有default case 的select语句会永远阻塞。
|
|
Return statements - return 语句
函数F中的 “return“语句终止了F的执行,并且可以选择提供一个或多个结果值。在F返回给它的调用者之前,任何由F延迟的函数都会被执行。
ReturnStmt = "return" [ ExpressionList ] .
在没有结果类型的函数中,"return“语句必须不指定任何结果值。
|
|
有三种方法可以从一个有结果类型的函数中返回值:
-
可以在 “
return“语句中明确列出一个或多个返回值。每个表达式必须是单值的,并且可以分配给函数的结果类型的相应元素。1 2 3 4 5 6 7func simpleF() int { return 2 } func complexF1() (re float64, im float64) { return -7.0, -4.0 } -
“
return“语句中的表达式列表可能是对一个多值函数的单一调用。其效果就像从该函数返回的每个值都被分配到一个临时变量中,其类型为相应的值,随后的 “return“语句列出了这些变量,此时,前一种情况的规则适用。1 2 3func complexF2() (re float64, im float64) { return complexF1() } -
如果函数的结果类型为其结果参数指定了名称,表达式列表可能是空的。结果参数作为普通的局部变量,函数可以根据需要给它们赋值。
return语句会返回这些变量的值。1 2 3 4 5 6 7 8 9 10func complexF3() (re float64, im float64) { re = 7.0 im = 4.0 return } func (devnull) Write(p []byte) (n int, _ error) { n = len(p) return }
不管它们是如何被声明的,所有的结果值在进入函数时都被初始化为其类型的零值。指定结果的 “return“语句在执行任何延迟函数之前设置结果参数。
实现限制:如果在返回的地方有一个与结果参数同名的不同实体(常量、类型或变量)在作用域内,编译器可能不允许在 “return“语句中出现空表达式列表。
|
|
Break statements - break 语句
“break “语句可以终止同一函数中最里面的 “for"、"switch “或 “select “语句的执行。
BreakStmt = "break" [ Label ] .
如果有一个标签,它必须是一个封闭的 “for"、"switch “或 “select “语句的标签,而且是执行终止的那一个。
|
|
Continue statements - continue 语句
“continue “语句通过将控制推进到循环块的末端来开始最内层的 “for “循环的下一次迭代。"for “循环必须是在同一个函数中。
ContinueStmt = "continue" [ Label ] .
如果有一个标签,它必须是一个封闭的 “for “语句的标签,而且是执行前进的那一个。
|
|
Goto statements 语句 goto
“goto “语句将控制转移到同一函数中具有相应标签的语句。
GotoStmt = "goto" Label .
goto Error
执行 “goto “语句不能导致任何变量进入goto处的作用域之外的作用域。例如,这个例子:
|
|
是错误的,因为跳转到标签L时,跳过了创建v的过程。
块外的 “goto “语句不能跳到该块内的标签。例如,这个例子:
|
|
是错误的,因为标签L1在 “for “语句的块内,而goto不在其中。
Fallthrough statements 语句 fallthrough
在表达式开关语句中,"fallthrough “语句将控制转移到下一个case子句的第一个语句。它只能作为这种子句中的最后一个非空语句使用。
FallthroughStmt = "fallthrough" .
Defer statements 语句 defer
“defer“语句调用一个函数,该函数的执行被推迟到外层函数返回的那一刻,或者是因为外层函数执行了 return 语句,达到了其函数体的末端,或者是因为相应的goroutine正在恐慌。
DeferStmt = "defer" Expression .
这个表达式必须是一个函数或方法的调用;它不能是被圆括号括起来的。对内置函数的调用与表达式语句一样受到限制。
每次执行 “defer “语句时,函数值和调用的参数像往常一样被求值并重新保存,但实际的函数不会被调用。相反,被延迟函数在外层的函数返回之前立即被调用,其顺序与它们被延迟的顺序相反。也就是说,如果外层的函数通过一个明确的 return 语句返回,被延迟函数在任何结果参数被该 reurn 语句设置后执行,但在外层函数返回给其调用者之前。如果被延迟函数值被求值为nil,那么在调用该被延迟函数时会出现执行恐慌(而不是当 “defer “语句被执行时)。
例如,如果被延迟函数是一个函数字面量,并且外层的函数有在该字面量的作用域内的命名结果参数,那么该被延迟函数可以在这些结果参数被返回之前访问和修改它们。如果被延迟函数有任何返回值,这些返回值将在函数完成时被丢弃。(参见处理恐慌一节)。
|
|
1.1.13 - 内置函数
Built-in functions 内置函数
内置函数是预先声明的。它们像其他函数一样被调用,但其中一些函数接受一个类型而非表达式作为其第一个实参。
内置函数没有标准的Go类型,所以它们只能出现在调用表达式中;它们不能作为函数值使用。
Close
对于一个核心类型为通道的参数ch,内置函数close记录了通道上将不再有任何值被发送。如果ch是一个仅接收的通道,那么(关闭它)是一个错误。发送到或关闭一个已关闭的通道会导致运行时恐慌。关闭nil通道也会引起运行时恐慌。在调用close后,并且在任何先前发送的值被接收后,接收操作将返回通道类型的零值而不阻塞。多值接收操作会返回一个接收值以及通道是否被关闭的指示。
Length and capacity 长度和容量
内置函数len和cap接受各种类型的实参并返回int类型的结果。该实现保证结果总是适合于一个int。
Call Argument type Result
调用 实参类型 结果
len(s) string type string length in bytes
[n]T, *[n]T array length (== n)
[]T slice length
map[K]T map length (number of defined keys)
chan T number of elements queued in channel buffer
type parameter see below
cap(s) [n]T, *[n]T array length (== n)
[]T slice capacity
chan T channel buffer capacity
type parameter see below
如果参数类型是一个类型参数P,调用len(e)(或cap(e))必须对P的类型集中的每个类型有效。其结果是(类型对应P被实例化时使用的类型实参的)实参的长度(或容量)。
切片的容量是底层数组中分配到的元素的数量。在任何时候,以下关系都是成立的:
0 <= len(s) <= cap(s)
nil切片、nil映射或nil通道的长度是0。nil切片或nil通道的容量是0。
如果s是一个字符串常量,那么表达式len(s)就是常量。如果s的类型是一个数组或指向数组的指针,并且表达式s不包含通道接收或(非常量)函数调用,那么表达式len(s)和cap(s)是常量;在这种情况下,s不被求值。否则,len和cap的调用不是常量,s被求值。
|
|
Allocation 分配
内置函数new接收一个类型T,在运行时为该类型的变量分配存储空间,并返回一个指向它的*T类型的值。该变量被初始化,如初始值一节中所述。
|
|
举例来说
|
|
为一个S类型的变量分配存储空间,初始化它(a=0, b=0.0),并返回一个包含该位置地址的*S类型的值。
Making slices, maps and channels 制作切片、映射和通道
内置函数make接收一个类型T,后面可以选择一个特定类型的表达式列表。T的核心类型必须是一个切片、映射或通道。它返回一个类型为T(不是*T)的值。内存被初始化,如初始值一节中所述。
Call Core type Result
make(T, n) slice slice of type T with length n and capacity n
make(T, n, m) slice slice of type T with length n and capacity m
make(T) map map of type T
make(T, n) map map of type T with initial space for approximately n elements
make(T) channel unbuffered channel of type T
make(T, n) channel buffered channel of type T, buffer size n
每个大小实参n和m必须是整型,或者是一个只包含整型的类型集,或者是一个无类型的常量。一个常量大小参数必须是非负数,并且可以用int类型的值表示;如果它是一个无类型的常量,它被赋予int类型。如果n和m都被提供并且是常量,那么n必须不大于m。对于切片和通道,如果n在运行时是负数或者大于m,就会发生运行时恐慌。
|
|
调用map类型和大小提示n的make将创建一个初始空间可容纳n个map元素的map。具体的行为是依赖于实现的。
Appending to and copying slices 追加和复制切片
内置函数append和copy可以帮助进行常见的切片操作。对于这两个函数,其结果与实参所引用的内存是否重叠无关。
The variadic function append appends zero or more values x to a slice s and returns the resulting slice of the same type as s. The core type of s must be a slice of type []E. The values x are passed to a parameter of type ...E and the respective parameter passing rules apply. As a special case, if the core type of s is []byte, append also accepts a second argument with core type bytestring followed by .... This form appends the bytes of the byte slice or string.
可变参数函数append将零个或多个值x追加到一个切片s,并返回与s相同类型的结果切片。值x被传递给一个类型为...E的参数,各自的参数传递规则适用。作为一个特例,如果s的核心类型是[]byte,append也接受第二个参数,其核心类型是bytestring,后面是... 。这种形式追加了字节切片或字符串的字节。
|
|
如果s的容量不足以容纳额外的值,append会分配一个新的、足够大的底层数组,同时容纳现有的切片元素和额外的值。否则,append复用原来的底层数组。
|
|
函数copy将切片元素从源src复制到目标dst,并返回复制的元素数量。两个参数的核心类型必须是具有一致的元素类型的切片。复制的元素数是len(src)和len(dst)中的最小值。作为一种特殊情况,如果目标的核心类型是[]byte,copy也接受一个核心类型为bytestring的源参数。这种形式将字节切片或字符串中的字节复制到字节切片中。
|
|
例子:
|
|
Deletion of map elements 删除映射元素
内置函数delete可以从映射m中删除键值为k的元素,值k必须可以分配给m的键类型。
|
|
如果m的类型是类型参数,那么该类型集合中的所有类型必须是映射,并且它们必须都有相同的键类型。
如果映射m是nil或者元素m[k]不存在,delete就是一个空操作。
Manipulating complex numbers 操纵复数
有三个函数组装和分解复数。内置函数 complex 从浮点实部和虚部构造一个复数值,而 real 和 imag 则提取复数值的实部和虚部。
|
|
实参的类型和返回值相对应。对于complex函数,两个实参必须是相同的浮点类型,返回类型是具有对应浮点成分的复数类型:float32类型的实参对应comple64复数类型,而float64类型的实参对应comple128复数类型。如果其中一个实参的值是一个无类型常量,那么它首先会被隐式转换为另一个实参的类型。如果两个参数都求值为无类型常量,那么它们必须是非复数,或者它们的虚数部分必须为零,这样函数的返回值就是一个无类型的复数常量。
对于real和imag,实参必须是复数类型,返回类型是相应的浮点类型:float32对应complex64,float64对应complex128。如果实参的值是一个无类型的常量,它必须是一个数字,这样函数的返回值就是一个无类型的浮点常量。
real和imag函数一起构成了复数的逆运算,所以对于一个复数类型Z的值z来说,z == Z(complex(real(z), imag(z)))。
如果这些函数的操作数都是常量,返回值就是一个常量。
|
|
Arguments of type parameter type are not permitted.
不允许使用参数类型的实参。
Handling panics 处理恐慌
两个内置函数,panic和recover,协助报告和处理运行时恐慌和程序定义的错误情况。
|
|
在执行函数F时,对panic的显式调用或运行时恐慌终止了F的执行,然后被F延迟的任何函数会照常执行。接下来,任何被F的调用者延迟的函数都会被运行,以此类推,直到被执行中的goroutine中的顶级函数所延迟的任何函数。此时,程序被终止,错误情况被报告,包括panic的实参值。这个终止过程被称为panicking。
|
|
recover函数允许程序管理 panicking goroutine 的行为。假设函数G延迟了一个调用recover的函数D,并且在G执行的同一个goroutine上的一个函数发生了恐慌。当被延迟函数的运行到达D时,D调用recover的返回值将是传递给调用panic的值。如果D正常返回,没有启动新的panic,则 panicking goroutine 停止。在这种情况下,G和对panic的调用之间调用的函数的状态被丢弃,并恢复正常执行。G在D之前被延迟的任何函数随后被运行,G的执行通过返回给它的调用者而终止。
如果以下任何一个条件成立,recover的返回值为nil:
panic的参数是空的。- goroutine没有陷入panicking。
recover不是由被延迟函数直接调用的。
下面的例子中的protect函数调用了函数实参g,并保护调用者免受g引发的运行时恐慌。
|
|
Bootstrapping 引导
目前的实现提供了几个在引导(bootstrapping)过程中有用的内置函数。为了完整起见,这些函数被记录下来,但不保证会留在语言中。它们并不返回结果。
Function Behavior
print prints all arguments; formatting of arguments is implementation-specific => 打印所有实参;实参的格式化和实现有关
println like print but prints spaces between arguments and a newline at the end => 和 print 类似,但是会在每个实参间打印空格,在结尾打印新行
实现限制:print和println不一定需要接受任意的实参类型,但必须支持布尔型、数字型和字符串型的打印。
1.1.14 - 包
Packages 包
Go程序是通过链接包来构建的。一个包是由一个或多个源文件构成的,这些文件共同声明了属于该包的常量、类型、变量和函数,并且可以在同一包的所有文件中访问。这些元素可以导出并在另一个包中使用。
Source file organization 源文件组织
每个源文件都由一个 package 子句(package clause)组成,该子句定义了它所属的包,然后是一组可能为空的导入声明,这些导入声明声明了它希望使用的包的内容,然后是一组可能为空的函数、类型、变量和常量的声明。
SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
Package clause 包子句
每个源文件的开头都有一个包子句,定义了该文件所属的包。
PackageClause = "package" PackageName .
PackageName = identifier .
PackageName(包名)不能是空白标识符(即_)。
|
|
共享相同PackageName(包名)的一组文件构成了一个包的实现。实现可能会要求一个包的所有源文件存放在同一个目录中。
Import declarations 导入声明
导入声明指出,包含该声明的源文件依赖于导入包的功能(§程序初始化和执行),并且能够访问这些被导入的包的导出标识符。该导入命名了一个用于访问的标识符(PackageName 包名)和一个指定要导入的包的ImportPath(导入路径)。
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
PackageName (包名)用于限定标识符,以访问导入源文件中包的导出标识符。它被声明在文件块中。如果(导入声明中)PackageName(包名)被省略,则它默认为在导入包的包子句中指定的标识符。如果出现一个明确的句号(.)而不是名字,那么在该包的包块中声明的所有包的导出标识符将在导入源文件的文件块中声明,并且必须在没有限定符的情况下进行访问。
对ImportPath(导入路径)的解释是依赖于实现的,但它通常是已编译包的完整文件名的子字符串,并且可能是相对于已安装包的存储库的。
实现限制:编译器可以将ImportPaths(导入路径)限制为非空字符串,只使用属于Unicode的L、M、N、P和S一般类别的字符(不含空格的图形字符),也可能排除字符!"#$%&'()*,:;<=>?[\]^‘{|}和Unicode替换字符U+FFFD。
考虑一个包含包子句package math的编译包,它导出了函数Sin,并将编译包安装在由 “lib/math“标识的文件中。下表说明了在各种类型的导入声明之后,在导入包的文件中如何访问Sin。
Import declaration Local name of Sin
导入声明 本地 Sin 名
import "lib/math" math.Sin
import m "lib/math" m.Sin
import . "lib/math" Sin
导入声明声明了导入包和被导入包之间的依赖关系。如果一个包直接或间接地导入自身,或者直接导入一个包而不引用其任何导出的标识符,都是非法的。要导入一个包只为了它的副作用(初始化),可以使用空白标识符(即_)作为显式的包名:
import _ "lib/math"
An example package 一个包的例子
下面是一个完整的Go包,它实现了一个并发素数筛选。
|
|
1.1.15 - 程序初始化和执行
Program initialization and execution 程序初始化和执行
原文:https://go.dev/ref/spec#Program_initialization_and_execution
The zero value 零值
当通过声明或调用new为一个变量分配存储空间时,或者通过复合字面量或调用make创建一个新的值时,如果没有提供明确的初始化,该变量或值将被赋予一个默认值。这种变量或值的每个元素都被设置为其类型的零值:布尔类型为false,数值型为0,字符串为"",指针、函数、接口、切片、通道和映射为nil。这种初始化是递归进行的,因此,举例来说,如果没有指定值,结构体数组的每个元素字段都将被设为零值。
这两个简单的声明是等同的:
|
|
在
|
|
之后,以下情况成立:
|
|
同样的情况,在以下情况下也会成立
|
|
Package initialization 包的初始化
在包内,包级别变量的初始化是逐步进行的,每一步都会选择声明顺序中最早的变量,该变量与未初始化的变量没有依赖关系。
更确切地说,如果包级别变量还没有被初始化,并且没有初始化表达式,或者它的初始化表达式与未初始化的变量没有依赖关系,那么这个包级别变量就被认为可以被初始化。初始化的过程是重复初始化在声明顺序中最早的、准备好初始化的下一个包级别变量,直到没有准备好初始化的变量。
如果在这个过程结束时,仍有任何变量未被初始化,那么这些变量就是一个或多个初始化循环的一部分,程序是无效的。
变量声明左侧的多个变量(由右侧的单个(多值)表达式来初始化)是一起被初始化的:如果左侧的任何一个变量被初始化,那么所有这些变量都在同一步骤中被初始化。
|
|
为了实现包的初始化,空白变量与声明中的其他变量一样被处理。
在多个文件中声明的变量的声明顺序是由文件呈现给编译器的顺序决定的。在第一个文件中声明的变量要在第二个文件中声明的任何变量之前声明,以此类推。
依赖性分析不依赖于变量的实际值,只依赖于源文件中对它们的词法引用,并进行传递性分析。例如,如果一个变量x的初始化表达式引用了一个函数,该函数的主体引用了变量y,那么x就依赖于y:
- 对变量或函数的引用是表示该变量或函数的标识符。
- 对一个方法
m的引用是一个方法值或者形式为t.m的方法表达式,其中t的(静态)类型不是一个接口类型,并且方法m在t的方法集中。是否调用结果函数值t.m并不重要。 - 如果
x的初始化表达式或主体(对于函数和方法)包含对y的引用,或者对依赖于y的函数或方法的引用,那么变量、函数或方法x就依赖于变量y。
例如,给定的声明有
|
|
初始化顺序是 d,b,c,a。注意初始化表达式中子表达式的顺序是不相关的:在这个例子中a = c + b和a = b + c的初始化顺序是一样的。
依赖性分析是按包进行的;只考虑引用当前包中声明的变量、函数和(非接口)方法。如果变量之间存在其他隐藏的数据依赖关系,那么这些变量之间的初始化顺序是未指定的。
例如,给定的声明有
|
|
变量a将在b之后被初始化,但x是在b之前、b和a之间还是在a之后被初始化,以及sideEffect()被调用的时刻(在x被初始化之前或之后)都是未指定的。
变量也可以使用在包块中声明的(不带实参,也没有结果参数)的名为init的函数来初始化。
|
|
每个包可以定义多个这样的(init)函数,甚至在一个源文件中也可以(有多个init函数)。在包块中,init标识符只能用于声明init函数,但标识符本身并没有被声明。因此,init函数不能在程序中的任何地方被引用。
一个没有导入的包(即没有使用导入声明的包)的初始化方法是给它所有的包级别变量分配初始值,然后按照它们在源文件中出现的顺序调用所有的init函数,可能是在多个文件中出现,就像提交给编译器一样。如果一个包有导入(即使用了导入声明),那么在初始化包本身之前,被导入的包会先被初始化。如果多个包导入了一个包,那么被导入的包将只被初始化一次。 by construction,导入包可以保证不存在循环初始化依赖。
包的初始化 —— 变量的初始化和init函数的调用 —— 发生在单一goroutine中,按顺序,一次一个包。init函数可以启动其他goroutines,这些goroutines 可以与初始化代码同时运行。不过,初始化过程总是对init函数进行排序:在前一个函数返回之前,它不会调用下一个函数。
为了保证初始化行为的可重复性,我们鼓励构建系统以词法文件名的顺序向编译器提交属于同一包的多个文件。
Program execution 程序执行
一个完整的程序是通过将一个名为(单个非导入包)main包与它所导入的所有包链接起来而创建的。主包必须有包名main,并声明一个不接受实参且不返回值的main函数。
|
|
程序的执行从初始化main包开始,然后调用函数main。当该函数调用返回时,程序退出。它不会等待其他(非main)goroutine完成。
1.1.16 - 错误
Errors 错误
预先声明的error类型被定义为
|
|
它是代表错误条件的常规接口,nil值代表没有错误。例如,可以定义一个从文件中读取数据的函数:
|
|
1.1.17 - 运行时恐慌
Run-time panics 运行时恐慌
执行错误,如试图对一个数组进行超界索引,会触发运行时恐慌,它等同于带由实现所定义的接口类型 runtime.Error 的值来对内置函数 panic 的调用。这个类型满足预先声明的接口类型error。表示不同的运行时错误条件的确切的错误值是未指定的。
|
|
1.1.18 - 系统考虑
System considerations 系统考虑
原文:[https://go.dev/ref/spec#System considerations](https://go.dev/ref/spec#System considerations)
Package unsafe - unsafe 包
编译器知道的内置包unsafe,可以通过导入路径 “unsafe “访问,它为低级编程提供了便利,包括违反(violate)类型系统的操作。使用unsafe的包必须手动审查其类型安全,并且可能无法移植。该包提供以下接口:
|
|
Pointer是一个指针类型,但是Pointer的值不能被解除引用。任何底层类型为uintptr的指针或值都可以被转换为底层类型Pointer的类型,反之亦然。在Pointer和uintptr之间转换的效果是由实现定义的。
|
|
Alignof和Sizeof函数接收任意类型的表达式x,并分别返回假设变量v的对齐方式或大小,就像v通过var v = x声明一样。
Offsetof函数接收一个(可能是括号内的)选择器s.f,表示由s或*s表示的结构体中的字段f,并返回相对于该结构体地址的字段偏移量(字节)。如果f是一个嵌入字段,它必须可以通过结构体的字段在没有指针间接的情况下访问。对于带有字段f的结构体s:
|
|
计算机体系结构可能要求内存地址被对齐;也就是说,变量的地址必须是一个因子的倍数,即变量类型的对齐方式。函数Alignof接收一个表示任何类型的变量的表达式,并返回(该类型的)变量的对齐方式,单位为字节。对于变量x:
|
|
如果T是一个类型参数,或者它是一个包含可变大小的元素或字段的数组或结构体类型,则T类型的(变量)具有可变大小。否则,大小是常量。如果对 Alignof、Offsetof 和 Sizeof 的调用的实参(或 Offsetof 的选择器表达式 s.f 中的结构体 s)是恒定大小的类型,则它们是 uintptr 类型的编译时常量表达式。
Add 函数将 len 添加到 ptr 并返回更新后的指针 unsafe.Pointer(uintptr(ptr) + uintptr(len)) 。len实参必须是整数类型或无类型的常量。一个常量len实参必须可以用int类型的值表示;如果它是一个无类型的常量,则它会被赋予int类型。Pointer的有效使用规则仍然适用。
Slice 函数返回一个切片,其底层数组从 ptr 开始,其长度和容量为 len。Slice(ptr, len) 等于
|
|
除了这样,还有一种特殊情况,如果 ptr 是 nil 并且 len 是零,Slice 返回 nil。
len实参必须是整数类型或无类型的常量。一个常量len实参必须是非负的,并且可以用int类型的值表示;如果它是一个无类型的常量,则它会被赋予int类型。在运行时,如果len是负的,或者如果ptr是nil而len不是0,会发生运行时恐慌。
Size and alignment guarantees 大小和对齐保证
对于数值型,以下大小是有保证的:
|
|
以下最小对齐特性得到了保证:
- 对于任何类型的变量
x:unsafe.Alignof(x)至少是1。 - 对于结构体类型的变量
x:unsafe.Alignof(x)是x的每个字段f的所有值unsafe.Alignof(x.f)中最大的一个,但至少是1。 - 对于数组类型的变量
x:unsafe.Alignof(x)与数组元素类型的变量的对齐方式相同。
如果结构体或数组类型不包含大小大于0的字段(或元素),那么它的大小就是零。两个不同的zero-size变量在内存中可能有相同的地址。
1.2 - Go内存模型
The Go Memory Model - Go内存模型
Version of June 6, 2022
2022年6月6日版本
简介
Go的内存模型指定了在一个goroutine中读取一个变量时,可以保证观察到在另一个goroutine中对同一变量进行写入产生的值的条件。
建议
同时被多个goroutine访问的数据的修改程序必须序列化这样的访问。
为了序列化访问,请使用通道操作或其他同步原语,例如sync和sync/atomic包中的原语。
如果您必须阅读本文档的其余部分才能理解程序的行为,那么您正在过于聪明。
不要自作聪明(don’t be clever)
非正式概述
Go以与语言的其余部分类似的方式处理其内存模型,旨在保持语义简单、易于理解和有用。本节对方法进行了一般概述,对大多数程序员来说应该足够了。内存模型在下一节中更正式地指定。
数据竞争被定义为同时发生对同一位置的内存写入和读取或写入,除非所有访问都是由sync/atomic包提供的原子数据访问。正如已经注意到的那样,程序员强烈建议使用适当的同步来避免数据竞争。在没有数据竞争的情况下,Go程序的行为就像所有的goroutines都被多路复用到一个单处理器上一样。这个属性有时被称为DRF-SC:data-race-free程序以顺序一致的方式执行。
尽管程序员应该编写没有数据竞争的Go程序,但对于Go实现在响应数据竞争时能做什么存在一些限制。一个实现可以始终通过报告竞争并终止程序来响应数据竞争。否则,单字长或子字长内存位置的每次读取都必须观察到实际写入到该位置的值(也许是由并发执行的goroutine写入的),而且尚未被覆盖。这些实现约束使Go更像Java或JavaScript,因为大多数竞赛有限的结果,而不像C和C++,其中任何有竞赛的程序的含义完全未定义,编译器可以做任何事情。Go的方法旨在使出错的程序更可靠、更易于调试,同时仍然坚持竞赛是错误的,工具可以诊断和报告它们。
内存模型
Go的内存模型的正式定义紧密遵循了Hans-J. Boehm和Sarita V. Adve在2008年PLDI发表的“C++并发内存模型基础”中提出的方法。无数据竞争程序的定义以及无竞争程序的顺序一致性保证等同于该工作中的定义。
内存模型描述了由goroutine执行组成的程序执行所需的条件,这些goroutine执行由内存操作组成。
内存操作由四个细节模拟:
- 其类型,指示它是普通数据读取,普通数据写入还是同步操作,例如原子数据访问、互斥操作或通道操作。
- 它在程序中的位置。
- 正在访问的内存位置或变量。
- 操作读取或写入的值。
某些内存操作类似于读操作,包括读取、原子读取、互斥锁和通道接收。其他内存操作类似于写操作,包括写入、原子写入、互斥解锁、通道发送和通道关闭。有些操作,例如原子比较和交换,既是读操作又是写操作。
goroutine执行被建模为单个goroutine执行的一组内存操作。
要求1:每个goroutine中的内存操作必须对应于该goroutine的正确顺序执行,给定从内存读取和写入的值。该执行必须与排序之前关系一致,该关系定义了Go语言规范中Go的控制流构造的部分序列需求以及表达式的求值顺序。
Go程序执行被建模为一组goroutine执行,以及指定每个读取操作从哪个写入操作读取的映射W。(同一程序的多个执行可能具有不同的程序执行。)
要求2:对于给定的程序执行,映射W(当限制为同步操作时)必须可以通过某些隐式同步操作的总序来解释,该总序与这些操作读取和写入的值以及排序一致。
同步之前的关系是来自W的同步内存操作的部分序。如果同步读取类内存操作r观察到同步写入类内存操作w(即,如果W(r)=w),则w在r之前同步。简单来说,同步之前的关系是前面段落提到的暗示的总序的子集,限于W直接观察的信息。
发生之前的关系定义为顺序之前和同步之前关系的联合的传递闭包。
要求3:对于内存位置x上的普通(非同步)数据读取r,W(r)必须是对r可见的写入w,其中可见的意思是以下两个条件都满足:
- w先于r发生。
- w不先于发生在r之前的任何其他写入w’(到x)。
关于内存位置x上的读写数据竞争,由一个读取类的内存操作r和一个写入类的内存操作w组成,其中至少有一个操作不是同步操作,并且这两个操作在happens before中没有顺序(即r既不先于w也不后于w)。
关于内存位置x上的写写数据竞争,由两个写入类的内存操作w和w’组成,其中至少有一个操作不是同步操作,并且这两个操作在happens before中没有顺序。
注意,如果在内存位置x上没有读写或写写数据竞争,则任何读取r在W(r)中只有一个可能性:即在happens before顺序中立即在其之前的单个w。
更普遍地,可以证明,任何没有数据竞争的Go程序,即没有具有读写或写写数据竞争的程序执行,只能由goroutine执行的一些顺序一致地交错来解释结果。 (证明与上述引用的Boehm和Adve论文的第7节相同。)该属性称为DRF-SC。
正式定义的目的是与其他语言(包括C,C ++,Java,JavaScript,Rust和Swift)提供给无竞争程序的DRF-SC保证相匹配。
某些Go语言操作(例如goroutine创建和内存分配)充当同步操作。这些操作对同步之前的部分顺序的影响在下面的“同步”部分中有所记录。各个包负责为其自己的操作提供类似的文档。
含有数据竞争的程序的实现限制
前面的部分给出了数据竞争-free程序执行的形式化定义。本部分非正式地描述了实现必须为包含数据竞争的程序提供的语义。
首先,任何实现都可以在检测到数据竞争时报告竞争并停止程序的执行。使用ThreadSanitizer的实现(使用“go build -race”访问)正是这样做的。
否则,不大于机器字的内存位置x的读取r必须观察到某个写入w,使得r不在w之前发生,且不存在另一个写入w’,使得w发生在w’之前且w’在r之前发生。也就是说,每个读取必须观察到一个前面或并发写入的值。
此外,不允许观察到非因果和“凭空”的写入。
鼓励但不要求对单个机器字大小的内存位置进行读取,以满足与大小为字的内存位置相同的语义,观察单个允许的写入w。出于性能原因,实现可以将较大的操作视为一组未指定顺序的单个机器字大小的操作。这意味着,多字数据结构上的竞争可能会导致不对应于单个写入的不一致值。当值取决于内部(指针、长度)或(指针、类型)对的一致性时,例如在大多数Go实现中的接口值、映射、切片和字符串中,这种竞争反过来又可能导致任意的内存损坏。
下面的“不正确的同步”部分提供了不正确同步的示例。
下面的“错误编译”部分提供了实现的限制示例。
同步
初始化
程序初始化在一个goroutine中运行,但该goroutine可能会创建其他并发运行的goroutine。
如果包p导入包q,则q的init函数的完成会在p的任何一个函数的开始之前完成。
所有init函数的完成在函数main.main的开始之前进行同步。
goroutine 创建
启动新的goroutine的go语句在goroutine的执行开始之前进行同步。
例如,在这个程序中:
|
|
调用hello将在将来的某个时候打印"hello, world"(也许在hello返回之后)。
goroutine 销毁
退出 goroutine 的行为不能保证在程序中的任何事件之前同步。例如,在以下程序中:
|
|
对 a 的赋值没有任何同步事件跟随,因此不能保证被任何其他 goroutine 观察到。实际上,一个激进的编译器可能会删除整个 go 语句。
如果一个 goroutine 的影响必须被另一个 goroutine 观察到,请使用同步机制,如锁或通道通信来建立相对顺序。
通道通信
通道通信是goroutines间同步的主要方法。每次对特定通道的发送操作都匹配到该通道的相应接收操作,通常在不同的协程中执行。
对于特定通道的发送操作在相应接收操作完成之前同步。
下面的程序:
|
|
保证打印出"hello, world"。写操作 a 先于通道 c 的发送操作,而该发送操作在相应接收操作完成之前同步,接着写操作 a 在打印操作之前完成。
当通道关闭时,返回零值的接收操作之前同步通道的关闭。
在上一个示例中,将 c <- 0 替换为 close(c) 将产生相同保证的程序。
从一个非缓冲通道中接收数据,在相应发送操作完成之前进行同步。
下面这个程序(与上面相同,但发送和接收语句交换,使用非缓冲通道):
|
|
同样保证打印出"hello, world"。写操作 a 先于通道 c 的接收操作,而该接收操作在相应发送操作完成之前同步,接着写操作 a 在打印操作之前完成。
如果通道被缓冲(例如 c = make(chan int, 1)),则程序不能保证打印出"hello, world"。(它可能打印出空字符串、崩溃或执行其他操作)。
第 k 次接收操作在具有容量 C 的通道上完成之前同步于第 k+C 次发送操作完成。
此规则将前一个规则推广到缓冲通道。它允许通过缓冲通道建立计数信号量:通道中的项目数对应于活动使用的数量,通道的容量对应于同时使用的最大数量,发送项目获取信号量,接收项目释放信号量。这是限制并发性的常见惯用语。
该程序对于工作列表中的每个条目启动一个协程,但协程使用 limit 通道进行协调,以确保最多有三个工作函数同时运行。
|
|
锁
sync包实现了两种锁数据类型,sync.Mutex和sync.RWMutex。
对于任意sync.Mutex或sync.RWMutex变量l和n < m,调用l.Unlock()的n必须在调用l.Lock()的m返回之前同步。
该程序:
|
|
保证会打印“hello, world”。f中的第一个l.Unlock()调用在main中的第二个l.Lock()调用返回之前同步,而这在打印之前排序。
对于sync.RWMutex变量l上的任何l.RLock调用,都有一个n,使得第n次l.Unlock调用在l.RLock返回之前同步,匹配的l.RUnlock调用在第n + 1次调用l.Lock的返回之前同步。
对sync.Mutex和sync.RWMutex变量调用l.TryLock(或l.TryRLock)的成功调用等效于调用l.Lock(或l.RLock)。失败的调用没有同步效果。就内存模型而言,即使互斥锁l未锁定,l.TryLock(或l.TryRLock)也可以被认为有可能返回false。
Once
sync包提供了Once类型的安全初始化机制,用于处理多个goroutine的存在。多个线程可以执行once.Do(f)来执行特定的f函数,但只有一个将运行f(),其他调用会被阻塞,直到f()返回。
对于once.Do(f)的单个调用的f()的完成,在任何对once.Do(f)的调用返回之前同步。
该程序:
|
|
调用twoprint将仅调用setup一次。setup函数将在任何print调用之前完成。结果将是打印两次“hello, world”。
原子值
sync/atomic包中的API是可以用于同步不同goroutine执行的“原子操作”。如果原子操作A的效果被原子操作B观察到,则A在B之前同步。在程序中执行的所有原子操作的行为好像按某种顺序一致地执行。
上述定义与C ++的顺序一致的原子操作和Java的易失变量具有相同的语义。
Finalizers 终结者
runtime包提供了SetFinalizer函数,该函数会在程序不再使用某个特定对象时调用终结器(finalizer)。对于调用SetFinalizer(x, f)的程序,x的终结器函数f(x)的调用与之前的SetFinalizer调用之间是同步的。
其他机制
sync包提供了额外的同步抽象,包括条件变量、无锁映射、分配池和等待组。每个同步抽象的文档都会说明它所做出的同步保证。
提供同步抽象的其他包也应该说明它们所做出的保证。
错误的同步
带有数据竞争的程序是错误的,可能会导致非顺序一致性执行。特别地,需要注意的是,读取操作r可能会观察到与r并发执行的任何写入操作w写入的值。即使这样,它也不意味着在r之后发生的读取会观察到w之前发生的写入。
在下面的程序中:
|
|
函数g可能会打印2,然后再打印0。
这个事实使得一些常见的惯用法变得无效。
Double-checked locking是为了避免同步的开销。例如,twoprint程序可能会写成不正确的形式:
|
|
但是,没有保证在doprint中观察到done的写入意味着观察到a的写入。这个版本可能会(不正确地)打印空字符串而不是“hello, world”。
另一个不正确的习惯是忙等待一个值,如下所示:
|
|
与前面一样,在main中观察到done的写入并不意味着观察到a的写入,因此该程序也可能打印空字符串。更糟糕的是,没有保证done的写入将被main观察到,因为两个线程之间没有同步事件。main中的循环不能保证结束。
还有更微妙的变体,例如下面的程序:
|
|
即使main观察到g != nil并退出其循环,也不能保证它将观察到g.msg的初始化值。
在所有这些示例中,解决方案都是相同的:使用显式同步。
不正确的编译
Go 内存模型限制编译器优化的程度与限制 Go 程序一样。某些在单线程程序中有效的编译器优化在所有 Go 程序中并不有效。特别地,编译器不能引入原始程序中不存在的写操作,也不能使单个读取操作观察到多个值,并且不能允许单个写入操作写入多个值。
以下所有示例均假定 *p 和 *q 引用对多个 goroutine 可访问的内存位置。
不要在无竞争的程序中引入数据竞争,这意味着不要将写操作移出它们出现在的条件语句中。例如,编译器不应该翻转以下程序中的条件语句:
|
|
也就是说,编译器不应该将程序重写为:
|
|
如果 cond 为 false,并且另一个 goroutine 正在读取 *p,则在原始程序中,其他 goroutine 只能观察到 *p 的先前任何值和 1。在重写后的程序中,其他 goroutine 可以观察到先前不可能出现的值 2。
不要在无竞争的程序中引入数据竞争,这也意味着不要假设循环一定会终止。例如,在以下程序中,编译器通常不能将对 *p 或 *q 的访问移到循环之前:
|
|
如果 list 指向一个循环链表,则原始程序永远不会访问 *p 或 *q,但重写后的程序会访问。如果编译器可以证明 *p 不会 panic,那么将 *p 移到循环之前是安全的;将 *q 移到循环之前也需要编译器证明没有其他 goroutine 可以访问 *q。
不要在无竞争的程序中引入数据竞争,这也意味着不要假设被调用的函数总是返回或不包含同步操作。例如,在以下程序中,编译器不应该在函数调用之前移动对 *p 或 *q 的访问(至少不应该没有对 f 的确切行为有直接了解):
|
|
如果该调用永远不返回,则原始程序将不会访问 *p 或 *q,但是重写后的程序将会访问。如果调用包含同步操作,则原始程序可以建立到 *p 和 *q 访问之前的 happens-before 关系,但重写后的程序则不能。
不允许一个读取操作观察到多个值意味着不从共享内存中重新加载本地变量。例如,在这个程序中,编译器不得丢弃i并在funcs[i]()之前重新加载i = *p:
|
|
如果复杂的代码需要许多寄存器,单线程程序的编译器可以在不保存副本的情况下放弃i,然后在funcs [i]()之前重新加载i = *p。 Go编译器不允许,因为*p的值可能已经改变。(相反,编译器可以将i溢出到堆栈。)
不允许单个写入操作写入多个值也意味着不要在写入之前使用本地变量将写入内存用作临时存储。例如,在此程序中,编译器不得在*p中使用临时存储:
|
|
也就是说,它不得将程序重写为:
|
|
如果i和*p起初相等于2,则原始代码会执行*p = 3,因此竞争线程只能从*p读取2或3。重写代码执行*p = 1,然后*p = 3,允许竞争线程也读取1。
请注意,所有这些优化在C / C ++编译器中都是允许的:与C / C ++编译器共享后端的Go编译器必须注意禁用对Go无效的优化。
请注意,如果编译器可以证明竞争不会影响目标平台上的正确执行,则禁止引入数据竞争并不适用。例如,在基本上所有CPU上,将
|
|
转换为:
|
|
只要能够证明*shared在访问时不会故障,因为潜在的添加读取不会影响任何现有的并发读取或写入。另一方面,转换在源到源转换器中无效。
结论
编写无数据竞争程序的Go程序员可以依赖这些程序的顺序一致的执行,就像其他现代编程语言一样。
在涉及具有竞争关系的程序时,程序员和编译器都应记住这些建议:不要自作聪明(don’t be clever)。
1.3 - 命令文档
1.3.1 - 全部命令
| Name | Synopsis 简述 |
|---|---|
| addr2line | addr2line是对GNU addr2line工具的最小模拟,刚好足以支持pprof。 |
| api | api 计算一组 Go 包的导出 API。 |
| asm | asm,通常以 “go tool asm “进行调用,它将源文件组装成一个对象文件,该文件以参数源文件的基名命名,并带有.o后缀。 |
| buildid | buildid 显示或更新存储在 Go 包或二进制文件中的构建 ID。 |
| cgo | cgo 可以创建调用 C 代码的 Go 包。 |
| compile | compile ,通常以 “go tool compile “调用,编译一个由命令行上命名的文件组成的单一 Go 包。 |
| cover | cover 是一个用于分析由 “go test -coverprofile=cover.out “生成的覆盖率配置文件的程序。 |
| dist | dist 帮助引导、构建和测试 Go 发行版。 |
| doc | doc(通常以 go doc 的形式运行)接受零个、一个或两个参数。 |
| fix | fix 找到使用旧 API 的 Go 程序,并将其改写为使用新的 API。 |
| go | go 是一个管理 Go 源代码的工具。 |
| gofmt | gofmt 用于格式化 Go 程序。 |
| link | link,通常以 “go tool link “的方式调用,读取包main的Go存档或对象,以及它的依赖项,并将它们组合成可执行的二进制文件。 |
| nm | nm 列出对象文件、存档、可执行文件等所定义或使用的符号。 |
| objdump | objdump 反汇编可执行文件。 |
| pack | pack 是传统 Unix ar 工具的一个简单版本。 |
| pprof | pprof 解释并显示 Go 程序的配置文件。 |
| test2json | test2json 将 Go 测试输出转换为机器可读的 JSON 流。 |
| trace | trace 是一个用于查看跟踪文件的工具。 |
| vet | vet 检查 Go 源代码并报告可疑的结构,例如实参与格式字符串不一致的 Printf 调用。 |
| internal | |
| archive | archive 包实现了对 Go 工具链生成的归档文件的读取。 |
| bio | bio 包实现了 Go 工具链中使用的常见 I/O 抽象。 |
| browser | browser包提供了与用户的浏览器进行交互的实用工具。 |
| buildid | |
| codesign | codesign包为Mach-O文件的临时代码签名提供基本功能。 |
| dwarf | dwarf包生成DWARF调试信息。 |
| edit | edit包实现了对字节切片的基于位置的缓冲编辑。 |
| gcprog | gcprog包为打包的 GC 指针位图实现了一个编码器(被称为GC程序)。 |
| goobj | |
| notsha256 | notsha256包实现了NOTSHA256算法,这是一个散列,定义为 SHA256的按位 NOT。 |
| obj | |
| obj/arm | |
| obj/arm64 | arm64包实现了一个ARM64汇编器。 |
| obj/loong64 | |
| obj/mips | |
| obj/ppc64 | ppc64 包实现了一个 PPC64 汇编器,它将 Go asm 汇编成 Power ISA 3.0B 所定义的相应 PPC64 指令。 |
| obj/riscv | |
| obj/s390x | |
| obj/wasm | |
| obj/x86 | |
| objabi | |
| objfile | objfile包实现了对操作系统特定可执行文件的可移植访问。 |
| osinfo | osinfo包提供了操作系统元数据。 |
| pkgpath | pkgpath 包决定了 gccgo/GoLLVM 符号所使用的包路径。 |
| quoted | quoted包提供了字符串操作的实用工具。 |
| src | |
| sys | |
| test2json | test2json包实现了测试二进制输出到JSON的转换。 |
| traceviewer | traceviewer包提供了Chrome trace viewer所使用的JSON数据结构的定义。 |
1.3.2 - internal
1.3.2.1 - brower
1.3.2.2 - buildid
1.3.2.3 - codesign
1.3.2.4 - dwarf
1.3.2.5 - edit
1.3.2.6 - gcprog
1.3.2.7 - goobj
1.3.2.8 - notsha256
1.3.2.9 - obj
1.3.2.10 - obj_arm
1.3.2.11 - obj_arm64
1.3.2.12 - obj_loong62
1.3.2.13 - obj_mips
1.3.2.14 - obj_ppc64
1.3.2.15 - obj_riscv
1.3.2.16 - obj_s390x
1.3.2.17 - obj_wasm
1.3.2.18 - obj_x86
1.3.2.19 - objabi
1.3.2.20 - objfile
1.3.2.21 - osinfo
1.3.2.22 - pkgpath
1.3.2.23 - quoted
1.3.2.24 - src
1.3.2.25 - sys
1.3.2.26 - test2json
1.3.2.27 - traceviewer
1.3.2.28 - archive
1.3.2.29 - bio
1.3.3 - addr2line
addr2line
Overview 概述
addr2line是对GNU addr2line工具的最小模拟,足以支持pprof。
使用方法:
go tool addr2line binary
addr2line从标准输入中读取十六进制地址,每行一个,前缀为可选的0x。对于每个输入地址,addr2line打印两个输出行,首先是包含该地址的函数名称,其次是该地址对应的源代码的file:line。
这个工具仅用于pprof;它的接口可能会改变,或者在未来的版本中被完全删除。
=== “main.go”
|
|
=== “addr2line_test.go”
|
|
1.3.4 - api
api
Overview
api计算一组Go包的导出API。
=== “goapi.go”
|
|
1.3.5 - asm
asm
原文:https://pkg.go.dev/cmd/asm@go1.19.3
Overview 概述
asm,通常以 “go tool asm “调用,将源文件组装成一个对象文件,该文件以参数源文件的基本名称命名,并使用.o后缀。之后,该对象文件可以与其他对象组合成一个包存档。
Command Line 命令行
使用方法:
go tool asm [flags] file
指定的 file 必须是一个Go汇编文件。所有的目标操作系统和体系结构都使用同一个汇编器。GOOS和GOARCH环境变量设置所需的目标。
标志:
-D name[=value]
Predefine symbol name with an optional simple value.
Can be repeated to define multiple symbols.
=> 用一个可选的简单值预先定义符号名称。
可以重复定义多个符号。
-I dir1 -I dir2
Search for #include files in dir1, dir2, etc,
after consulting $GOROOT/pkg/$GOOS_$GOARCH.
=> 搜索dir1、dir2等地方的#include文件。
在查阅了$GOROOT/pkg/$GOOS_$GOARCH之后。
-S
Print assembly and machine code.
=> 打印汇编和机器代码。
-V
Print assembler version and exit.
=> 打印汇编程序版本并退出。
-debug
Dump instructions as they are parsed.
=> 在解析指令的过程中倾倒指令。
-dynlink
Support references to Go symbols defined in other shared libraries.
=> 支持对其他共享库中定义的 Go 符号的引用。
-gensymabis
Write symbol ABI information to output file. Don't assemble.
=> 将符号ABI信息写入输出文件。不要组装。
-o file
Write output to file. The default is foo.o for /a/b/c/foo.s.
=> 将输出写入文件。默认是/a/b/c/foo.s的foo.o。
-shared
Generate code that can be linked into a shared library.
=> 生成可以被链接到共享库中的代码。
-spectre list
Enable spectre mitigations in list (all, ret).
=> 在列表中启用spectre缓解措施(全部,ret)。
-trimpath prefix
Remove prefix from recorded source file paths.
=> 从记录的源文件路径中移除前缀。
Input language:
输入语言:
The assembler uses mostly the same syntax for all architectures, the main variation having to do with addressing modes. Input is run through a simplified C preprocessor that implements #include, #define, #ifdef/endif, but not #if or ##.
汇编器对所有的架构都使用相同的语法,主要的变化是与寻址模式有关。输入是通过一个简化的C预处理器运行的,它实现了#include、#define、#ifdef/endif,但没有#if或##。
更多信息请参见https://golang.org/doc/asm。
=== “doc.go”
=== “main.go”
1.3.6 - buildid
buildid
Overview
Buildid displays or updates the build ID stored in a Go package or binary.
Usage:
go tool buildid [-w] file
By default, buildid prints the build ID found in the named file. If the -w option is given, buildid rewrites the build ID found in the file to accurately record a content hash of the file.
This tool is only intended for use by the go command or other build systems.
=== “buildid.go”
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"flag"
"fmt"
"log"
"os"
"strings"
"cmd/internal/buildid"
)
func usage() {
fmt.Fprintf(os.Stderr, "usage: go tool buildid [-w] file\n")
flag.PrintDefaults()
os.Exit(2)
}
var wflag = flag.Bool("w", false, "write build ID")
func main() {
log.SetPrefix("buildid: ")
log.SetFlags(0)
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 {
usage()
}
file := flag.Arg(0)
id, err := buildid.ReadFile(file)
if err != nil {
log.Fatal(err)
}
if !*wflag {
fmt.Printf("%s\n", id)
return
}
// Keep in sync with src/cmd/go/internal/work/buildid.go:updateBuildID
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
matches, hash, err := buildid.FindAndHash(f, id, 0)
f.Close()
if err != nil {
log.Fatal(err)
}
// <= go 1.7 doesn't embed the contentID or actionID, so no slash is present
if !strings.Contains(id, "/") {
log.Fatalf("%s: build ID is a legacy format...binary too old for this tool", file)
}
newID := id[:strings.LastIndex(id, "/")] + "/" + buildid.HashToString(hash)
if len(newID) != len(id) {
log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID)
}
if len(matches) == 0 {
return
}
f, err = os.OpenFile(file, os.O_RDWR, 0)
if err != nil {
log.Fatal(err)
}
if err := buildid.Rewrite(f, matches, newID); err != nil {
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
=== “doc.go”
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Buildid displays or updates the build ID stored in a Go package or binary.
Usage:
go tool buildid [-w] file
By default, buildid prints the build ID found in the named file.
If the -w option is given, buildid rewrites the build ID found in
the file to accurately record a content hash of the file.
This tool is only intended for use by the go command or
other build systems.
*/
package main
1.3.7 - cgo
cgo
原文:https://pkg.go.dev/cmd/cgo@go1.19.3
Overview [¶(https://pkg.go.dev/cmd/cgo@go1.19.3#pkg-overview)
Cgo enables the creation of Go packages that call C code.
Using cgo with the go command
To use cgo write normal Go code that imports a pseudo-package “C”. The Go code can then refer to types such as C.size_t, variables such as C.stdout, or functions such as C.putchar.
If the import of “C” is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:
// #include <stdio.h>
// #include <errno.h>
import "C"
The preamble may contain any C code, including function and variable declarations and definitions. These may then be referred to from Go code as though they were defined in the package “C”. All names declared in the preamble may be used, even if they start with a lower-case letter. Exception: static variables in the preamble may not be referenced from Go code; static functions are permitted.
See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See “C? Go? Cgo!” for an introduction to using cgo: https://golang.org/doc/articles/c_go_cgo.html.
CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS may be defined with pseudo #cgo directives within these comments to tweak the behavior of the C, C++ or Fortran compiler. Values defined in multiple directives are concatenated together. The directive can include a list of build constraints limiting its effect to systems satisfying one of the constraints (see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax). For example:
// #cgo CFLAGS: -DPNG_DEBUG=1
// #cgo amd64 386 CFLAGS: -DX86=1
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"
Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config tool using a ‘#cgo pkg-config:’ directive followed by the package names. For example:
// #cgo pkg-config: png cairo
// #include <png.h>
import "C"
The default pkg-config tool may be changed by setting the PKG_CONFIG environment variable.
For security reasons, only a limited set of flags are allowed, notably -D, -U, -I, and -l. To allow additional flags, set CGO_CFLAGS_ALLOW to a regular expression matching the new flags. To disallow flags that would otherwise be allowed, set CGO_CFLAGS_DISALLOW to a regular expression matching arguments that must be disallowed. In both cases the regular expression must match a full argument: to allow -mfoo=bar, use CGO_CFLAGS_ALLOW=’-mfoo.*’, not just CGO_CFLAGS_ALLOW=’-mfoo’. Similarly named variables control the allowed CPPFLAGS, CXXFLAGS, FFLAGS, and LDFLAGS.
Also for security reasons, only a limited set of characters are permitted, notably alphanumeric characters and a few symbols, such as ‘.’, that will not be interpreted in unexpected ways. Attempts to use forbidden characters will get a “malformed #cgo argument” error.
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and CGO_LDFLAGS environment variables are added to the flags derived from these directives. Package-specific flags should be set using the directives, not the environment variables, so that builds work in unmodified environments. Flags obtained from environment variables are not subject to the security limitations described above.
All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and used to compile C files in that package. All the CPPFLAGS and CXXFLAGS directives in a package are concatenated and used to compile C++ files in that package. All the CPPFLAGS and FFLAGS directives in a package are concatenated and used to compile Fortran files in that package. All the LDFLAGS directives in any package in the program are concatenated and used at link time. All the pkg-config directives are concatenated and sent to pkg-config simultaneously to add to each appropriate set of command-line flags.
When the cgo directives are parsed, any occurrence of the string ${SRCDIR} will be replaced by the absolute path to the directory containing the source file. This allows pre-compiled static libraries to be included in the package directory and linked properly. For example if package foo is in the directory /go/src/foo:
// #cgo LDFLAGS: -L${SRCDIR}/libs -lfoo
Will be expanded to:
// #cgo LDFLAGS: -L/go/src/foo/libs -lfoo
When the Go tool sees that one or more Go files use the special import “C”, it will look for other non-Go files in the directory and compile them as part of the Go package. Any .c, .s, .S or .sx files will be compiled with the C compiler. Any .cc, .cpp, or .cxx files will be compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will not be compiled separately, but, if these header files are changed, the package (including its non-Go source files) will be recompiled. Note that changes to files in other directories do not cause the package to be recompiled, so all non-Go source code for the package should be stored in the package directory, not in subdirectories. The default C and C++ compilers may be changed by the CC and CXX environment variables, respectively; those environment variables may include command line options.
The cgo tool will always invoke the C compiler with the source file’s directory in the include path; i.e. -I${SRCDIR} is always implied. This means that if a header file foo/bar.h exists both in the source directory and also in the system include directory (or some other place specified by a -I flag), then “#include <foo/bar.h>” will always find the local version in preference to any other version.
The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling. You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it. The go tool will set the build constraint “cgo” if cgo is enabled. The special import “C” implies the “cgo” build constraint, as though the file also said “// +build cgo”. Therefore, if cgo is disabled, files that import “C” will not be built by the go tool. (For more about build constraints see https://golang.org/pkg/go/build/#hdr-Build_Constraints).
When cross-compiling, you must specify a C cross-compiler for cgo to use. You can do this by setting the generic CC_FOR_TARGET or the more specific CC_FOR_${GOOS}_${GOARCH} (for example, CC_FOR_linux_arm) environment variable when building the toolchain using make.bash, or you can set the CC environment variable any time you run the go tool.
The CXX_FOR_TARGET, CXX_FOR_${GOOS}_${GOARCH}, and CXX environment variables work in a similar way for C++ code.
Go references to C
Within the Go file, C’s struct field names that are keywords in Go can be accessed by prefixing them with an underscore: if x points at a C struct with a field named “type”, x._type accesses the field. C struct fields that cannot be expressed in Go, such as bit fields or misaligned data, are omitted in the Go struct, replaced by appropriate padding to reach the next field or the end of the struct.
The standard C numeric types are available under the names C.char, C.schar (signed char), C.uchar (unsigned char), C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int), C.long, C.ulong (unsigned long), C.longlong (long long), C.ulonglong (unsigned long long), C.float, C.double, C.complexfloat (complex float), and C.complexdouble (complex double). The C type void* is represented by Go’s unsafe.Pointer. The C types __int128_t and __uint128_t are represented by [16]byte.
A few special C types which would normally be represented by a pointer type in Go are instead represented by a uintptr. See the Special cases section below.
To access a struct, union, or enum type directly, prefix it with struct_, union_, or enum_, as in C.struct_stat.
The size of any C type T is available as C.sizeof_T, as in C.sizeof_struct_stat.
A C function may be declared in the Go file with a parameter type of the special name GoString. This function may be called with an ordinary Go string value. The string length, and a pointer to the string contents, may be accessed by calling the C functions
size_t _GoStringLen(_GoString_ s);
const char *_GoStringPtr(_GoString_ s);
These functions are only available in the preamble, not in other C files. The C code must not modify the contents of the pointer returned by _GoStringPtr. Note that the string contents may not have a trailing NUL byte.
As Go doesn’t have support for C’s union type in the general case, C’s union types are represented as a Go byte array with the same length.
Go structs cannot embed fields with C types.
Go code cannot refer to zero-sized fields that occur at the end of non-empty C structs. To get the address of such a field (which is the only operation you can do with a zero-sized field) you must take the address of the struct and add the size of the struct.
Cgo translates C types into equivalent unexported Go types. Because the translations are unexported, a Go package should not expose C types in its exported API: a C type used in one Go package is different from the same C type used in another.
Any C function (even void functions) may be called in a multiple assignment context to retrieve both the return value (if any) and the C errno variable as an error (use _ to skip the result value if the function returns void). For example:
n, err = C.sqrt(-1)
_, err := C.voidFunc()
var n, err = C.sqrt(1)
Calling C function pointers is currently not supported, however you can declare Go variables which hold C function pointers and pass them back and forth between Go and C. C code may call function pointers received from Go. For example:
package main
// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
// return f();
// }
//
// int fortytwo()
// {
// return 42;
// }
import "C"
import "fmt"
func main() {
f := C.intFunc(C.fortytwo)
fmt.Println(int(C.bridge_int_func(f)))
// Output: 42
}
In C, a function argument written as a fixed size array actually requires a pointer to the first element of the array. C compilers are aware of this calling convention and adjust the call accordingly, but Go cannot. In Go, you must pass the pointer to the first element explicitly: C.f(&C.x[0]).
Calling variadic C functions is not supported. It is possible to circumvent this by using a C function wrapper. For example:
package main
// #include <stdio.h>
// #include <stdlib.h>
//
// static void myprint(char* s) {
// printf("%s\n", s);
// }
import "C"
import "unsafe"
func main() {
cs := C.CString("Hello from stdio")
C.myprint(cs)
C.free(unsafe.Pointer(cs))
}
A few special functions convert between Go and C types by making copies of the data. In pseudo-Go definitions:
// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
// Go []byte slice to C array
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CBytes([]byte) unsafe.Pointer
// C string to Go string
func C.GoString(*C.char) string
// C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string
// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
As a special case, C.malloc does not call the C library malloc directly but instead calls a Go helper function that wraps the C library malloc but guarantees never to return nil. If C’s malloc indicates out of memory, the helper function crashes the program, like when Go itself runs out of memory. Because C.malloc cannot fail, it has no two-result form that returns errno.
C references to Go
Go functions can be exported for use by C code in the following way:
//export MyFunction
func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
//export MyFunction2
func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}
They will be available in the C code as:
extern GoInt64 MyFunction(int arg1, int arg2, GoString arg3);
extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
found in the _cgo_export.h generated header, after any preambles copied from the cgo input files. Functions with multiple return values are mapped to functions returning a struct.
Not all Go types can be mapped to C types in a useful way. Go struct types are not supported; use a C struct type. Go array types are not supported; use a C pointer.
Go functions that take arguments of type string may be called with the C type GoString, described above. The GoString type will be automatically defined in the preamble. Note that there is no way for C code to create a value of this type; this is only useful for passing string values from Go to C and back to Go.
Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations. If a file contains both definitions and declarations, then the two output files will produce duplicate symbols and the linker will fail. To avoid this, definitions must be placed in preambles in other files, or in C source files.
Passing pointers
Go is a garbage collected language, and the garbage collector needs to know the location of every pointer to Go memory. Because of this, there are restrictions on passing pointers between Go and C.
In this section the term Go pointer means a pointer to memory allocated by Go (such as by using the & operator or calling the predefined new function) and the term C pointer means a pointer to memory allocated by C (such as by a call to C.malloc). Whether a pointer is a Go pointer or a C pointer is a dynamic property determined by how the memory was allocated; it has nothing to do with the type of the pointer.
Note that values of some Go types, other than the type’s zero value, always include Go pointers. This is true of string, slice, interface, channel, map, and function types. A pointer type may hold a Go pointer or a C pointer. Array and struct types may or may not include Go pointers, depending on the element types. All the discussion below about Go pointers applies not just to pointer types, but also to other types that include Go pointers.
Go code may pass a Go pointer to C provided the Go memory to which it points does not contain any Go pointers. The C code must preserve this property: it must not store any Go pointers in Go memory, even temporarily. When passing a pointer to a field in a struct, the Go memory in question is the memory occupied by the field, not the entire struct. When passing a pointer to an element in an array or slice, the Go memory in question is the entire array or the entire backing array of the slice.
C code may not keep a copy of a Go pointer after the call returns. This includes the GoString type, which, as noted above, includes a Go pointer; GoString values may not be retained by C code.
A Go function called by C code may not return a Go pointer (which implies that it may not return a string, slice, channel, and so forth). A Go function called by C code may take C pointers as arguments, and it may store non-pointer or C pointer data through those pointers, but it may not store a Go pointer in memory pointed to by a C pointer. A Go function called by C code may take a Go pointer as an argument, but it must preserve the property that the Go memory to which it points does not contain any Go pointers.
Go code may not store a Go pointer in C memory. C code may store Go pointers in C memory, subject to the rule above: it must stop storing the Go pointer when the C function returns.
These rules are checked dynamically at runtime. The checking is controlled by the cgocheck setting of the GODEBUG environment variable. The default setting is GODEBUG=cgocheck=1, which implements reasonably cheap dynamic checks. These checks may be disabled entirely using GODEBUG=cgocheck=0. Complete checking of pointer handling, at some cost in run time, is available via GODEBUG=cgocheck=2.
It is possible to defeat this enforcement by using the unsafe package, and of course there is nothing stopping the C code from doing anything it likes. However, programs that break these rules are likely to fail in unexpected and unpredictable ways.
The runtime/cgo.Handle type can be used to safely pass Go values between Go and C. See the runtime/cgo package documentation for details.
Note: the current implementation has a bug. While Go code is permitted to write nil or a C pointer (but not a Go pointer) to C memory, the current implementation may sometimes cause a runtime error if the contents of the C memory appear to be a Go pointer. Therefore, avoid passing uninitialized C memory to Go code if the Go code is going to store pointer values in it. Zero out the memory in C before passing it to Go.
Special cases
A few special C types which would normally be represented by a pointer type in Go are instead represented by a uintptr. Those include:
\1. The *Ref types on Darwin, rooted at CoreFoundation’s CFTypeRef type.
\2. The object types from Java’s JNI interface:
jobject
jclass
jthrowable
jstring
jarray
jbooleanArray
jbyteArray
jcharArray
jshortArray
jintArray
jlongArray
jfloatArray
jdoubleArray
jobjectArray
jweak
\3. The EGLDisplay and EGLConfig types from the EGL API.
These types are uintptr on the Go side because they would otherwise confuse the Go garbage collector; they are sometimes not really pointers but data structures encoded in a pointer type. All operations on these types must happen in C. The proper constant to initialize an empty such reference is 0, not nil.
These special cases were introduced in Go 1.10. For auto-updating code from Go 1.9 and earlier, use the cftype or jni rewrites in the Go fix tool:
go tool fix -r cftype <pkg>
go tool fix -r jni <pkg>
It will replace nil with 0 in the appropriate places.
The EGLDisplay case was introduced in Go 1.12. Use the egl rewrite to auto-update code from Go 1.11 and earlier:
go tool fix -r egl <pkg>
The EGLConfig case was introduced in Go 1.15. Use the eglconf rewrite to auto-update code from Go 1.14 and earlier:
go tool fix -r eglconf <pkg>
Using cgo directly
Usage:
go tool cgo [cgo options] [-- compiler options] gofiles...
Cgo transforms the specified input Go source files into several output Go and C source files.
The compiler options are passed through uninterpreted when invoking the C compiler to compile the C parts of the package.
The following options are available when running cgo directly:
-V
Print cgo version and exit.
-debug-define
Debugging option. Print #defines.
-debug-gcc
Debugging option. Trace C compiler execution and output.
-dynimport file
Write list of symbols imported by file. Write to
-dynout argument or to standard output. Used by go
build when building a cgo package.
-dynlinker
Write dynamic linker as part of -dynimport output.
-dynout file
Write -dynimport output to file.
-dynpackage package
Set Go package for -dynimport output.
-exportheader file
If there are any exported functions, write the
generated export declarations to file.
C code can #include this to see the declarations.
-importpath string
The import path for the Go package. Optional; used for
nicer comments in the generated files.
-import_runtime_cgo
If set (which it is by default) import runtime/cgo in
generated output.
-import_syscall
If set (which it is by default) import syscall in
generated output.
-gccgo
Generate output for the gccgo compiler rather than the
gc compiler.
-gccgoprefix prefix
The -fgo-prefix option to be used with gccgo.
-gccgopkgpath path
The -fgo-pkgpath option to be used with gccgo.
-godefs
Write out input file in Go syntax replacing C package
names with real values. Used to generate files in the
syscall package when bootstrapping a new target.
-objdir directory
Put all generated files in directory.
-srcdir directory
1.3.8 - compile
compile
Overview
Compile, typically invoked as “go tool compile,” compiles a single Go package comprising the files named on the command line. It then writes a single object file named for the basename of the first source file with a .o suffix. The object file can then be combined with other objects into a package archive or passed directly to the linker (“go tool link”). If invoked with -pack, the compiler writes an archive directly, bypassing the intermediate object file.
The generated files contain type information about the symbols exported by the package and about types used by symbols imported by the package from other packages. It is therefore not necessary when compiling client C of package P to read the files of P’s dependencies, only the compiled output of P.
Command Line
Usage:
go tool compile [flags] file...
The specified files must be Go source files and all part of the same package. The same compiler is used for all target operating systems and architectures. The GOOS and GOARCH environment variables set the desired target.
Flags:
-D path
Set relative path for local imports.
-I dir1 -I dir2
Search for imported packages in dir1, dir2, etc,
after consulting $GOROOT/pkg/$GOOS_$GOARCH.
-L
Show complete file path in error messages.
-N
Disable optimizations.
-S
Print assembly listing to standard output (code only).
-S -S
Print assembly listing to standard output (code and data).
-V
Print compiler version and exit.
-asmhdr file
Write assembly header to file.
-asan
Insert calls to C/C++ address sanitizer.
-buildid id
Record id as the build id in the export metadata.
-blockprofile file
Write block profile for the compilation to file.
-c int
Concurrency during compilation. Set 1 for no concurrency (default is 1).
-complete
Assume package has no non-Go components.
-cpuprofile file
Write a CPU profile for the compilation to file.
-dynlink
Allow references to Go symbols in shared libraries (experimental).
-e
Remove the limit on the number of errors reported (default limit is 10).
-goversion string
Specify required go tool version of the runtime.
Exits when the runtime go version does not match goversion.
-h
Halt with a stack trace at the first error detected.
-importcfg file
Read import configuration from file.
In the file, set importmap, packagefile to specify import resolution.
-installsuffix suffix
Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
instead of $GOROOT/pkg/$GOOS_$GOARCH.
-l
Disable inlining.
-lang version
Set language version to compile, as in -lang=go1.12.
Default is current version.
-linkobj file
Write linker-specific object to file and compiler-specific
object to usual output file (as specified by -o).
Without this flag, the -o output is a combination of both
linker and compiler input.
-m
Print optimization decisions. Higher values or repetition
produce more detail.
-memprofile file
Write memory profile for the compilation to file.
-memprofilerate rate
Set runtime.MemProfileRate for the compilation to rate.
-msan
Insert calls to C/C++ memory sanitizer.
-mutexprofile file
Write mutex profile for the compilation to file.
-nolocalimports
Disallow local (relative) imports.
-o file
Write object to file (default file.o or, with -pack, file.a).
-p path
Set expected package import path for the code being compiled,
and diagnose imports that would cause a circular dependency.
-pack
Write a package (archive) file rather than an object file
-race
Compile with race detector enabled.
-s
Warn about composite literals that can be simplified.
-shared
Generate code that can be linked into a shared library.
-spectre list
Enable spectre mitigations in list (all, index, ret).
-traceprofile file
Write an execution trace to file.
-trimpath prefix
Remove prefix from recorded source file paths.
Flags related to debugging information:
-dwarf
Generate DWARF symbols.
-dwarflocationlists
Add location lists to DWARF in optimized mode.
-gendwarfinl int
Generate DWARF inline info records (default 2).
Flags to debug the compiler itself:
-E
Debug symbol export.
-K
Debug missing line numbers.
-d list
Print debug information about items in list. Try -d help for further information.
-live
Debug liveness analysis.
-v
Increase debug verbosity.
-%
Debug non-static initializers.
-W
Debug parse tree after type checking.
-f
Debug stack frames.
-i
Debug line number stack.
-j
Debug runtime-initialized variables.
-r
Debug generated wrappers.
-w
Debug type checking.
Compiler Directives
The compiler accepts directives in the form of comments. To distinguish them from non-directive comments, directives require no space between the comment opening and the name of the directive. However, since they are comments, tools unaware of the directive convention or of a particular directive can skip over a directive like any other comment.
Line directives come in several forms:
//line :line
//line :line:col
//line filename:line
//line filename:line:col
/*line :line*/
/*line :line:col*/
/*line filename:line*/
/*line filename:line:col*/
In order to be recognized as a line directive, the comment must start with //line or /*line followed by a space, and must contain at least one colon. The //line form must start at the beginning of a line. A line directive specifies the source position for the character immediately following the comment as having come from the specified file, line and column: For a //line comment, this is the first character of the next line, and for a /*line comment this is the character position immediately following the closing */. If no filename is given, the recorded filename is empty if there is also no column number; otherwise it is the most recently recorded filename (actual filename or filename specified by previous line directive). If a line directive doesn’t specify a column number, the column is “unknown” until the next directive and the compiler does not report column numbers for that range. The line directive text is interpreted from the back: First the trailing :ddd is peeled off from the directive text if ddd is a valid number > 0. Then the second :ddd is peeled off the same way if it is valid. Anything before that is considered the filename (possibly including blanks and colons). Invalid line or column values are reported as errors.
Examples:
//line foo.go:10 the filename is foo.go, and the line number is 10 for the next line
//line C:foo.go:10 colons are permitted in filenames, here the filename is C:foo.go, and the line is 10
//line a:100 :10 blanks are permitted in filenames, here the filename is " a:100 " (excluding quotes)
/*line :10:20*/x the position of x is in the current file with line number 10 and column number 20
/*line foo: 10 */ this comment is recognized as invalid line directive (extra blanks around line number)
Line directives typically appear in machine-generated code, so that compilers and debuggers will report positions in the original input to the generator.
The line directive is a historical special case; all other directives are of the form //go:name, indicating that they are defined by the Go toolchain. Each directive must be placed its own line, with only leading spaces and tabs allowed before the comment. Each directive applies to the Go code that immediately follows it, which typically must be a declaration.
//go:noescape
The //go:noescape directive must be followed by a function declaration without a body (meaning that the function has an implementation not written in Go). It specifies that the function does not allow any of the pointers passed as arguments to escape into the heap or into the values returned from the function. This information can be used during the compiler’s escape analysis of Go code calling the function.
//go:uintptrescapes
The //go:uintptrescapes directive must be followed by a function declaration. It specifies that the function’s uintptr arguments may be pointer values that have been converted to uintptr and must be on the heap and kept alive for the duration of the call, even though from the types alone it would appear that the object is no longer needed during the call. The conversion from pointer to uintptr must appear in the argument list of any call to this function. This directive is necessary for some low-level system call implementations and should be avoided otherwise.
//go:noinline
The //go:noinline directive must be followed by a function declaration. It specifies that calls to the function should not be inlined, overriding the compiler’s usual optimization rules. This is typically only needed for special runtime functions or when debugging the compiler.
//go:norace
The //go:norace directive must be followed by a function declaration. It specifies that the function’s memory accesses must be ignored by the race detector. This is most commonly used in low-level code invoked at times when it is unsafe to call into the race detector runtime.
//go:nosplit
The //go:nosplit directive must be followed by a function declaration. It specifies that the function must omit its usual stack overflow check. This is most commonly used by low-level runtime code invoked at times when it is unsafe for the calling goroutine to be preempted.
//go:linkname localname [importpath.name]
This special directive does not apply to the Go code that follows it. Instead, the //go:linkname directive instructs the compiler to use “importpath.name” as the object file symbol name for the variable or function declared as “localname” in the source code. If the “importpath.name” argument is omitted, the directive uses the symbol’s default object file symbol name and only has the effect of making the symbol accessible to other packages. Because this directive can subvert the type system and package modularity, it is only enabled in files that have imported “unsafe”.
=== “doc.go”
=== “main.go”
1.3.9 - cover
cover
Overview
Cover is a program for analyzing the coverage profiles generated by ‘go test -coverprofile=cover.out’.
Cover is also used by ‘go test -cover’ to rewrite the source code with annotations to track which parts of each function are executed. It operates on one Go source file at a time, computing approximate basic block information by studying the source. It is thus more portable than binary-rewriting coverage tools, but also a little less capable. For instance, it does not probe inside && and || expressions, and can be mildly confused by single statements with multiple function literals.
When computing coverage of a package that uses cgo, the cover tool must be applied to the output of cgo preprocessing, not the input, because cover deletes comments that are significant to cgo.
For usage information, please see:
|
|
=== “cover.go”
|
|
=== “cover_test.go”
|
|
=== “doc.go”
|
|
=== “func.go”
|
|
=== “html.go”
|
|
1.3.10 - dist
dist
Overview
Dist helps bootstrap, build, and test the Go distribution.
Usage:
go tool dist [command]
The commands are:
banner print installation banner
bootstrap rebuild everything
clean deletes all built files
env [-p] print environment (-p: include $PATH)
install [dir] install individual directory
list [-json] list all supported platforms
test [-h] run Go test(s)
version print Go version
1.3.11 - doc
doc
Overview
Doc (usually run as go doc) accepts zero, one or two arguments.
Zero arguments:
go doc
Show the documentation for the package in the current directory.
One argument:
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
The first item in this list that succeeds is the one whose documentation is printed. If there is a symbol but no package, the package in the current directory is chosen. However, if the argument begins with a capital letter it is always assumed to be a symbol in the current directory.
Two arguments:
go doc <pkg> <sym>[.<methodOrField>]
Show the documentation for the package, symbol, and method or field. The first argument must be a full package path. This is similar to the command-line usage for the godoc command.
For commands, unless the -cmd flag is present “go doc command” shows only the package-level docs for the package.
The -src flag causes doc to print the full source code for the symbol, such as the body of a struct, function or method.
The -all flag causes doc to print all documentation for the package and all its visible symbols. The argument must identify a package.
For complete documentation, run “go help doc”.
=== “dirs.go”
|
|
=== “doc_test.go”
|
|
=== “main.go”
|
|
=== “pkg.go”
|
|
1.3.12 - fix
fix
Overview
Fix finds Go programs that use old APIs and rewrites them to use newer ones. After you update to a new Go release, fix helps make the necessary changes to your programs.
Usage:
go tool fix [-r name,...] [path ...]
Without an explicit path, fix reads standard input and writes the result to standard output.
If the named path is a file, fix rewrites the named files in place. If the named path is a directory, fix rewrites all .go files in that directory tree. When fix rewrites a file, it prints a line to standard error giving the name of the file and the rewrite applied.
If the -diff flag is set, no files are rewritten. Instead fix prints the differences a rewrite would introduce.
The -r flag restricts the set of rewrites considered to those in the named list. By default fix considers all known rewrites. Fix’s rewrites are idempotent, so that it is safe to apply fix to updated or partially updated code even without using the -r flag.
Fix prints the full list of fixes it can apply in its help output; to see them, run go tool fix -help.
Fix does not make backup copies of the files that it edits. Instead, use a version control system’s “diff” functionality to inspect the changes that fix makes before committing them.
1.3.13 - go
go
https://pkg.go.dev/cmd/go@go1.20.1
Overview
go 是管理 Go 源代码的工具。
用法:
go <command> [arguments]
命令包括:
bug 开始一个 bug 报告
build 编译包和依赖项
clean 删除对象文件和缓存文件
doc 显示包或符号的文档
env 打印 Go 环境信息
fix 更新包以使用新的 API
fmt gofmt(重新格式化)包源代码
generate 通过处理源代码生成 Go 文件
get 添加依赖项到当前模块并安装它们
install 编译和安装包和依赖项
list 列出包或模块
mod 模块维护
work 工作区维护
run 编译并运行 Go 程序
test 测试包
tool 运行指定的 go 工具
version 打印 Go 版本
vet 报告包中可能存在的错误
使用"go help
其他帮助主题:
buildconstraint 构建限制条件
buildmode 构建模式
c Go 和 C 之间的调用
cache 构建和测试缓存
environment 环境变量
filetype 文件类型
go.mod go.mod 文件
gopath GOPATH 环境变量
gopath-get 传统 GOPATH go get
goproxy 模块代理协议
importpath 导入路径语法
modules 模块,模块版本等等
module-get 支持模块的 go get
module-auth 使用 go.sum 进行模块身份验证
packages 包列表和模式
private 配置以下载非公共代码
testflag 测试标志
testfunc 测试函数
vcs 使用 GOVCS 控制版本控制
使用"go help
开始一个 bug 报告
用法:
go bug
Bug 打开默认浏览器并启动一个新的 bug 报告。该报告包括有用的系统信息。
编译包和依赖项
用法:
go build [-o output] [build flags] [packages]
Build 编译由导入路径命名的包以及它们的依赖项,但不安装结果。
如果 build 的参数是来自单个目录的一组 .go 文件,则 build 将把它们视为指定单个包的源文件列表。
编译包时,build 忽略以”_test.go"结尾的文件。
当编译单个主包时,build 命令将生成的可执行文件写入以第一个源文件命名的输出文件(‘go build ed.go rx.go’ 会写入 ’ed’ 或 ’ed.exe’),或者写入源代码目录(‘go build unix/sam’ 会写入 ‘sam’ 或 ‘sam.exe’)。在 Windows 上编写可执行文件时,会添加 ‘.exe’ 后缀。
当编译多个包或单个非主包时,build 命令会编译这些包,但会丢弃生成的对象,只用于检查这些包是否能够被构建。
-o 标志强制 build 命令将生成的可执行文件或对象写入命名的输出文件或目录,而不是采用最后两段所述的默认行为。如果命名的输出是一个现有目录或以斜线或反斜线结尾,则任何生成的可执行文件都将写入该目录。
构建标志由 build、clean、get、install、list、run 和 test 命令共享:
-C dir
在运行命令之前切换到dir目录。
任何在命令行上命名的文件在更改目录之后解释。
-a
强制重新构建已经是最新版本的软件包。
-n
打印命令但不运行它们。
-p n
可以并行运行的程序数量,例如构建命令或测试二进制文件。
默认值为GOMAXPROCS,通常为可用CPU的数量。
-race
启用数据竞争检测。
仅在linux/amd64、freebsd/amd64、darwin/amd64、darwin/arm64、
windows/amd64、linux/ppc64le和linux/arm64上支持(仅适用于48位VMA)。
-msan
启用与内存污点检测器的互操作。
仅在linux/amd64、linux/arm64、freebsd/amd64上支持,
并且仅支持使用Clang/LLVM作为主机C编译器。
PIE构建模式将在除linux/amd64外的所有平台上使用。
-asan
启用与地址污点检测器的互操作。
仅在linux/arm64、linux/amd64上支持。
仅在linux/amd64或linux/arm64上支持,
并且仅支持使用GCC 7及更高版本或Clang/LLVM 9及更高版本。
-cover
启用代码覆盖率分析(需要设置GOEXPERIMENT=coverageredesign)。
-coverpkg pattern1,pattern2,pattern3
针对目标为'main'的构建(例如构建Go可执行文件),
将覆盖分析应用于与模式匹配的每个包。
默认情况下,将覆盖分析应用于主Go模块中的包。
有关包模式的说明,请参见"go help packages"。设置-cover。
-v
编译软件包时打印软件包名称。
-work
打印临时工作目录的名称,并在退出时不删除它。
-x
打印命令。
-asmflags '[pattern=]arg list'
在每个go工具asm调用中传递的参数。
-buildmode mode
要使用的构建模式。有关更多信息,请参见"go help buildmode"。
-buildvcs
是否在二进制文件中打印版本控制信息("true"、"false"或"auto")。
默认情况下("auto"),如果主包、包含它的主模块和当前目录都在同一个仓库中,
则将版本控制信息打印到二进制文件中。
使用-buildvcs=false始终省略版本控制信息,
或者使用-buildvcs=true,
如果版本控制信息可用但由于缺少工具或模糊的目录结构无法包含,则出错。
-compiler name
指定要使用的编译器名称,如 runtime.Compiler 中的 gccgo 或 gc。
-gccgoflags '[pattern=]arg list'
每个 gccgo 编译器/链接器调用传递的参数列表。
-gcflags '[pattern=]arg list'
每个 go 工具编译调用传递的参数列表。
-installsuffix suffix
用于包安装目录名称的后缀,以使输出与默认构建分开。
如果使用 -race 标志,
则自动将安装后缀设置为 race 或在显式设置后附加 _race。
-msan 和 -asan 标志同理。
使用需要非默认编译标志的 -buildmode 选项具有类似的效果。
-ldflags '[pattern=]arg list'
每个 go 工具链接调用传递的参数列表。
-linkshared
构建将链接到以 -buildmode=shared 创建的共享库的代码。
-mod mode
要使用的模块下载模式:readonly、vendor 或 mod。
默认情况下,如果存在 vendor 目录并且 go.mod 中的 go 版本为 1.14 或更高版本,
则 go 命令会像设置了 -mod=vendor 一样操作。
否则,go 命令会像设置了 -mod=readonly 一样操作。
有关详细信息,请参见 https://golang.org/ref/mod#build-commands。
-modcacherw
将新创建的目录保留在模块缓存中,以便进行读写,而不是只读。
-modfile file
在模块感知模式下,读取(并可能写入)替代 go.mod 文件,
而不是在模块根目录中的文件。
仍然必须存在名为"go.mod"的文件,以确定模块根目录,
但不会访问该文件。指定 -modfile 时,
还会使用替代 go.sum 文件:
其路径是通过从 -modfile 标志中删除".mod"扩展名并附加".sum"来派生的。
-overlay file
读取 JSON 配置文件,为构建操作提供覆盖。
文件是一个 JSON 结构,具有一个名为 'Replace' 的字段,
该字段将每个磁盘文件路径(一个字符串)映射到其支持文件路径,
以便在运行构建时,就像磁盘文件路径存在并具有由支持文件路径给定的内容一样,
或者如果其支持文件路径为空,则磁盘文件路径将不存在。
-overlay 标志的支持有一些限制:重要的是,
从外部包含的 cgo 文件必须与它们所包含的 Go 包在同一个目录中,
而覆盖在通过 go run 和 go test 运行二进制文件和测试时将不会出现。
-pgo file
指定用于编译时的基于概要文件的优化(PGO)的文件路径。
特殊名称"auto"将允许 go 命令在主包目录中选择名为"default.pgo"的文件
(如果存在)。
特殊名称"off"将关闭 PGO。
-pkgdir dir
安装和从 dir 加载所有包,而不是使用通常的位置。
例如,在使用非标准配置进行构建时,使用 -pkgdir 将生成的包保留在单独的位置。
-tags tag,list
一个逗号分隔的构建标记列表,表示要在构建期间考虑的额外构建标记。
有关构建标记的更多信息,请参见"go help buildconstraint"。
(Go 的早期版本使用空格分隔的列表,虽然这种形式已被弃用但仍然可以识别。)
-trimpath
从生成的可执行文件中删除所有文件系统路径。
记录的文件名将以模块路径@版本(在使用模块时)或普通的导入路径
(在使用标准库或 GOPATH 时)开头。
-toolexec 'cmd args'
用于调用类似 vet 和 asm 的工具链程序的程序。
例如,可以使用 -toolexec 来运行 asm 而不是直接运行,
go 命令将运行"cmd args /path/to/asm <arguments for asm>"。
TOOLEXEC_IMPORTPATH 环境变量将被设置,
与正在构建的包的"go list -f {{.ImportPath}}"匹配。
-asmflags、-gccgoflags、-gcflags 和 -ldflags 标志接受一个以空格分隔的参数列表,用于在构建期间传递给底层工具。要在列表中的元素中嵌入空格,请用单引号或双引号括起来。参数列表可以用包模式和等号开头,限制该参数列表仅适用于构建与该模式匹配的包(有关包模式的描述,请参见"go help packages”)。没有模式时,参数列表仅适用于命令行上指定的包。这些标志可以重复使用不同的模式,以便为不同的包集指定不同的参数。如果一个包匹配在多个标志中给定的模式,命令行上最后匹配的标志将覆盖之前的所有标志。例如,“go build -gcflags=-S fmt"仅为包fmt打印反汇编,而"go build -gcflags=all=-S fmt"为fmt及其所有依赖项打印反汇编。
有关包的详细信息,请参见"go help packages”。有关安装包和二进制文件的位置,请运行"go help gopath"。有关在 Go 和 C/C++ 之间调用的更多信息,请运行"go help c"。
注意:构建遵循某些约定,如"go help gopath"所述。然而,并非所有项目都能遵循这些约定。具有自己的约定或使用单独的软件构建系统的安装可能选择使用较低级别的调用,如"go tool compile"和"go tool link",以避免构建工具的一些开销和设计决策。
另请参阅:go install、go get、go clean。
删除对象文件和缓存文件
用法:
go clean [clean flags] [build flags] [packages]
clean从包源目录中删除对象文件。go命令在临时目录中构建大多数对象,因此go clean主要涉及其他工具或手动调用go build留下的对象文件。
如果给出了包参数或设置了-i或-r标志,则clean会从每个对应于导入路径的源目录中删除以下文件:
_obj/ 旧的对象目录,由Makefile留下
_test/ 旧的测试目录,由Makefile留下
_testmain.go 旧的 gotest 文件,由 Makefile 留下
test.out 旧的测试日志,由 Makefile 留下
build.out 旧的测试日志,由 Makefile 留下
*.[568ao] 由 Makefile 留下的对象文件
DIR(.exe) 通过 go build 生成的可执行文件
DIR.test(.exe) 通过 go test -c 生成的测试可执行文件
MAINFILE(.exe) 通过 go build MAINFILE.go 生成的可执行文件
*.so 由 SWIG 生成的文件
在列表中,DIR 表示目录的最终路径元素,而 MAINFILE 是目录中未包含在构建包中的任何 Go 源文件的基本名称。
-i 标志会使 clean 删除相应已安装的归档文件或二进制文件(相当于 ‘go install’)。
-n 标志会使 clean 打印出它将执行的删除命令,但不实际运行它们。
-r 标志会使 clean 递归应用于被导入路径命名的包的所有依赖项。
-x 标志会使 clean 打印出它执行删除命令的同时。
-cache 标志会使 clean 删除整个 go 构建缓存。
-testcache 标志会使 clean 过期 go 构建缓存中的所有测试结果。
-modcache 标志会使 clean 删除整个模块下载缓存,包括版本化依赖项的解压缩源代码。
-fuzzcache 标志会使 clean 删除用于模糊测试的存储在 Go 构建缓存中的文件。模糊引擎会缓存扩展代码覆盖率的文件,因此删除它们可能会使模糊测试变得不太有效,直到找到提供相同覆盖率的新输入。这些文件与存储在 testdata 目录中的文件不同;clean 不会删除这些文件。
有关构建标志的更多信息,请参阅 ‘go help build’。
有关指定包的更多信息,请参阅 ‘go help packages’。
显示包或符号的文档
用法:
go doc [doc flags] [package|[package.]symbol[.methodOrField]]
doc 打印与其参数所标识的项相关联的文档注释(一个包、常量、函数、类型、变量、方法或结构体字段),后跟每个该项"下面"一级项(一个包级别的声明、类型的方法等)的一行摘要。
doc 接受零个、一个或两个参数。
当不带参数运行时,即
go doc
它会打印当前目录中包的包文档。如果包是一个命令(package main),则除非提供了 -cmd 标志,否则该包的导出符号将从演示中省略。
当带有一个参数运行时,参数会被视为要文档化的项的 Go 语法样式表示形式。参数选择的内容取决于 GOROOT 和 GOPATH 中安装的内容,以及参数的形式,其概略如下:
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
列表中第一个匹配参数的项目是其文档将被打印的项目。(见下面的示例。)然而,如果参数以大写字母开头,则假定其为当前目录中标识符或方法。
对于包,扫描的顺序是按广度优先的词法顺序确定的。也就是说,呈现的包是与搜索匹配并且在其层次结构的根和词法上最先的包。在扫描GOPATH之前,始终完整扫描GOROOT树。
如果没有指定或匹配包,则选择当前目录中的包,因此"go doc Foo"会显示当前包中符号Foo的文档。
包路径必须是一个合格的路径或路径的后缀。go工具的常规包机制不适用于go doc。例如,包路径元素(如".“和”…")没有被实现。
当使用两个参数运行时,第一个参数是包路径(完整路径或后缀),第二个是符号或具有方法或结构字段的符号:
go doc <pkg> <sym>[.<methodOrField>]
在所有形式中,当匹配符号时,参数中的小写字母匹配任何情况,但大写字母匹配确切的情况。这意味着,如果不同的符号具有不同的情况,则小写参数在包中可能有多个匹配项。如果出现这种情况,则打印所有匹配项的文档。
示例:
|
|
标志:
-all
显示包中的所有文档。
-c
在匹配符号时区分大小写。
-cmd
将一个命令(package main)视为常规包。
否则,显示包的顶层文档时将隐藏 package main 的导出符号。
-short
每个符号显示一行的简要表示。
-src
显示符号的完整源代码。
这将显示其声明和定义的完整 Go 源代码,
例如函数定义(包括主体)、类型声明或封闭 const 块。
因此,输出可能包括未导出的详细信息。
-u
显示未导出的符号、方法和字段的文档,以及导出的文档。
打印Go环境信息
用法:
go env [-json] [-u] [-w] [var ...]
env打印Go环境信息。
默认情况下,env以shell脚本形式打印信息(在Windows上为批处理文件)。如果给出一个或多个变量名作为参数,env会在自己的行上打印每个命名变量的值。
-json标志以JSON格式而不是作为shell脚本打印环境。
-u标志需要一个或多个参数,并取消命名环境变量的默认设置,如果已使用"go env -w"设置。
-w标志需要一个或多个名称=值形式的参数,并将命名环境变量的默认设置更改为给定值。
有关环境变量的更多信息,请参见"go help environment"。
更新包以使用新API
用法:
go fix [-fix list] [packages]
fix在导入路径命名的包上运行Go fix命令。
-fix标志设置要运行的逗号分隔的修复程序列表。默认为所有已知修复程序。 (其值传递给"go tool fix -r"。)
有关修复程序的更多信息,请参见"go doc cmd/fix"。有关指定包的更多信息,请参见"go help packages"。
要使用其他选项运行fix,请运行"go tool fix"。
另请参见:go fmt,go vet。
Gofmt(重新格式化)包源
用法:
go fmt [-n] [-x] [packages]
fmt在导入路径命名的包上运行命令’gofmt -l -w’。它打印已修改的文件的名称。
有关gofmt的更多信息,请参见"go doc cmd/gofmt"。有关指定包的更多信息,请参见"go help packages"。
-n标志打印将被执行的命令。-x标志按它们被执行的方式打印命令。
-mod标志的值设置要使用的模块下载模式:readonly或vendor。有关更多信息,请参见"go help modules"。
要使用特定选项运行gofmt,请运行gofmt本身。
另请参见:go fix,go vet。
通过处理源文件生成Go文件
用法:
go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
generate 运行由现有文件中的指令描述的命令。这些命令可以运行任何进程,但是其意图是创建或更新 Go 源文件。
go generate 不会被 go build、go test 等自动运行。必须显式运行它。
go generate 扫描指令文件,这些文件的指令是一行文本,格式如下:
//go:generate command argument...
(注意:没有前导空格,也没有 “//go” 中的空格),其中 command 是要运行的生成器,对应于可以在本地运行的可执行文件。它必须在 shell 路径(gofmt)、完全限定路径(/usr/you/bin/mytool)或命令别名中。
请注意,go generate 不会解析文件,因此看起来像指令的行注释或多行字符串将被视为指令。
指令的参数是空格分隔的标记或双引号括起来的字符串,它们作为单独的参数传递给生成器在运行时。
引号括起来的字符串使用 Go 语法,并在执行之前进行评估;引号括起来的字符串在生成器中出现为单个参数。
为了让人类和机器工具知道代码是由生成器生成的,生成的源代码应该具有与以下正则表达式匹配的行(使用 Go 语法):
^// Code generated .* DO NOT EDIT\.$
该行必须出现在文件中第一个非注释、非空白文本之前。
在运行生成器时,go generate 设置了几个变量:
$GOARCH
执行的体系结构(arm、amd64 等)。
$GOOS
执行的操作系统(linux、windows 等)。
$GOFILE
文件的基本名称。
$GOLINE
源文件中指令的行号。
$GOPACKAGE
包含指令的文件的包的名称。
$GOROOT
调用生成器的 'go' 命令的 GOROOT 目录,其中包含 Go 工具链和标准库。
$DOLLAR
一个美元符号。
除了变量替换和引号括起来的字符串评估之外,命令行不执行任何特殊处理,例如 “globbing”。
作为执行命令前的最后一步,任何具有字母数字名称的环境变量调用(如$GOFILE或$HOME)都会在整个命令行中展开。变量扩展的语法在所有操作系统上均为$NAME。由于计算顺序,即使在引号内,变量也会被展开。如果未设置变量NAME,则$NAME会展开为空字符串。
以下是一个指令示例:
//go:generate -command xxx args...
该指令指定,在此源文件中,字符串xxx表示由参数标识的命令。这可用于创建别名或处理多个单词的生成器。例如:
//go:generate -command foo go tool foo
该指令指定命令"foo"表示生成器"go tool foo"。
在命令行中按照给定的顺序,逐一处理包,如果命令行列出了单个目录中的.go文件,则它们被视为单个包。在一个包内,按文件名顺序逐一处理源文件。在一个源文件内,生成器按它们出现在文件中的顺序逐一运行。go generate工具还设置了构建标记"generate",因此文件可以通过go generate进行检查,但在构建过程中会被忽略。
对于包含无效代码的包,generate仅处理具有有效包从句的源文件。
如果任何生成器返回错误的退出状态,则"go generate"跳过该包的所有后续处理。
生成器在包的源目录中运行。
go generate接受两个特定的标志:
-run=""
如果非空,则指定一个正则表达式,
以选择原始源文本(不包括任何尾随空格和最后一个换行符)与表达式匹配的指令。
-skip=""
如果非空,则指定一个正则表达式,
以抑制原始源文本(不包括任何尾随空格和最后一个换行符)与表达式匹配的指令。如果一个指令同时与-run和-skip参数匹配,则它将被跳过。
它还接受标准构建标志,包括-v、-n和-x。-v标志会在处理过程中打印包和文件的名称。-n标志会打印将要执行的命令。-x标志会打印正在执行的命令。
有关构建标志的更多信息,请参见"go help build"。
有关指定包的更多信息,请参见"go help packages"。
添加依赖项到当前模块并安装它们
用法:
go get [-t] [-u] [-v] [build flags] [packages]
get 将命令行参数解析为特定模块版本的包,更新 go.mod 以要求这些版本,并将源代码下载到模块缓存中。
要为包添加依赖项或将其升级到最新版本:
go get example.com/pkg
要升级或降级特定版本的包:
go get example.com/pkg@v1.2.3
要删除对模块的依赖项并降级需要它的模块:
go get example.com/mod@none
有关详情,请参见 Go模块参考中的go get命令。
在早期的 Go 版本中,“go get"用于构建和安装包。现在,“go get"专用于调整 go.mod 中的依赖项。“go install"可用于构建和安装命令。当指定版本时,“go install"以模块感知模式运行,并忽略当前目录中的 go.mod 文件。例如:
go install example.com/pkg@v1.2.3
go install example.com/pkg@latest
有关详情,请参见 ‘go help install’ 或 Go模块参考中的go install命令。
‘go get’ 接受以下标志:
-
-t标志指示 get 考虑构建命令行中指定的包的测试所需的模块。 -
-u标志指示 get 更新提供命令行中指定包的依赖项的模块以使用更高的次要或补丁版本。 -
-u=patch标志(不是 -u patch)也指示 get 更新依赖项,但将默认选择修补程序版本。
当 -t 和 -u 标志一起使用时,get 也会更新测试依赖项。
-x标志打印执行的命令。当直接从存储库下载模块时,这对于调试版本控制命令非常有用。
有关模块的更多信息,请参见 https://golang.org/ref/mod。
有关指定包的更多信息,请参见 ‘go help packages’。
本文描述了使用模块管理源代码和依赖项的 get 的行为。如果相反,go 命令在 GOPATH 模式下运行,则 get 的标志和效果的细节会改变,‘go help get’ 也会改变。请参阅 ‘go help gopath-get’。
另请参见:go build、go install、go clean、go mod。
编译和安装包及其依赖项
用法:
go install [build flags] [packages]
install 编译并安装导入路径指定的包。
可执行文件将被安装到名为GOBIN的目录中。默认情况下,GOBIN环境变量为$GOPATH/bin或者$HOME/go/bin(如果GOPATH环境变量未设置)。$GOROOT中的可执行文件将被安装到$GOROOT/bin或$GOTOOLDIR中,而不是$GOBIN中。
如果参数有版本后缀(如@latest或@v1.0.0),则"go install"将在模块感知模式下进行构建,忽略当前目录或任何父目录中的go.mod文件。这对于安装可执行文件而不影响主模块的依赖项非常有用。为了消除构建中使用的模块版本的歧义,参数必须满足以下限制:
- 参数必须是包路径或包模式(带有”…“通配符)。它们不能是标准包(如fmt),元模式(std,cmd,all)或相对或绝对文件路径。
- 所有参数必须具有相同的版本后缀。不允许不同的查询,即使它们引用同一个版本。
- 所有参数必须引用同一模块中的相同版本的包。
- 包路径参数必须引用主包。模式参数只会匹配主包。
- 没有模块被视为"主"模块。如果命令行上的包所在的模块有go.mod文件,则该文件不得包含指令(replace和exclude),使其被解释为与主模块不同。该模块不得要求其自身的更高版本。
- 任何模块中均不使用供应商目录。 (供应商目录未包含在"go install"下载的模块zip文件中。)
如果参数没有版本后缀,则"go install"可以在模块感知模式或GOPATH模式下运行,这取决于GO111MODULE环境变量和是否存在go.mod文件。有关详细信息,请参见"go help modules”。如果启用了模块感知模式,则"go install"在主模块的上下文中运行。
在禁用模块感知模式时,非主要包将安装在目录$GOPATH/pkg/$GOOS_$GOARCH中。启用模块感知模式时,非主要包将被构建和缓存,但不会被安装。
在 Go 1.20 之前,标准库被安装到$GOROOT/pkg/$GOOS_$GOARCH中。从 Go 1.20 开始,标准库被构建和缓存,但不会被安装。设置 GODEBUG=installgoroot=all 可以恢复对$GOROOT/pkg/$GOOS_$GOARCH的使用。
有关构建标志的更多信息,请参见"go help build”。有关指定软件包的更多信息,请参见"go help packages”。
另请参阅:go build、go get、go clean。
列出包或模块
用法:
go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
list 命令将指定的包列出,每个包占一行。最常用的标志是 -f 和 -json,它们控制打印每个包时输出的格式。其他的 list 标志在下面有说明,它们控制更具体的细节。
默认输出显示包的导入路径:
bytes
encoding/json
github.com/gorilla/mux
golang.org/x/net/html
-f 标志指定了列表的替代格式,使用包模板语法。默认输出相当于 -f '{{.ImportPath}}'。传递给模板的结构体是:
type Package struct {
Dir string // 包源文件所在的目录
ImportPath string // 包在目录中的导入路径
ImportComment string // 包声明的导入注释中的路径
Name string // 包名
Doc string // 包的文档字符串
Target string // 安装路径
Shlib string // 包含该包的共享库(仅在使用 -linkshared 时设置)
Goroot bool // 该包是否在 Go 根目录下?
Standard bool // 该包是否是标准 Go 库的一部分?
Stale bool // 对于该包,go install 是否会执行任何操作?
StaleReason string // Stale==true 的原因说明
Root string // 包所在的 Go 根目录或 Go path 目录
ConflictDir string // 此目录遮盖了 $GOPATH 中的 Dir
BinaryOnly bool // 仅限二进制包(不再支持)
ForTest string // 该包仅供命名测试使用
Export string // 包含导出数据的文件(使用 -export 时)
BuildID string // 编译包的 build ID(使用 -export 时)
Module *Module // 包所在模块的信息(如果有)(可能为 nil)
Match []string // 与此包匹配的命令行模式
DepOnly bool // 该包仅作为依赖项,没有被显式列出
// 源文件
GoFiles []string // .go 源文件(不包括 CgoFiles、TestGoFiles 和 XTestGoFiles)
CgoFiles []string // 导入了 "C" 的 .go 源文件
CompiledGoFiles []string // 向编译器展示的 .go 文件(使用 -compiled 时)
IgnoredGoFiles []string // 因构建约束而被忽略的 .go 源文件
IgnoredOtherFiles []string // 因构建约束而被忽略的非 .go 源文件
CFiles []string // .c 源文件
CXXFiles []string // .cc、.cxx 和 .cpp 源文件
MFiles []string // .m 源文件
HFiles []string // .h、.hh、.hpp 和 .hxx 源文件
FFiles []string // .f、.F、.for 和 .f90 Fortran 源文件
SFiles []string // .s 源文件
SwigFiles []string // .swig 文件
SwigCXXFiles []string // .swigcxx 文件
SysoFiles []string // 要添加到档案文件的 .syso 目标文件
TestGoFiles []string // 包内的 _test.go 文件
XTestGoFiles []string // 包外的 _test.go 文件
// 嵌入式文件
EmbedPatterns []string // //go:embed 模式
EmbedFiles []string // 由 EmbedPatterns 匹配的文件
TestEmbedPatterns []string // TestGoFiles 中的 //go:embed 模式
TestEmbedFiles []string // 由 TestEmbedPatterns 匹配的文件
XTestEmbedPatterns []string // XTestGoFiles 中的 //go:embed 模式
XTestEmbedFiles []string // 由 XTestEmbedPatterns 匹配的文件
// Cgo 指令
CgoCFLAGS []string // cgo:C 编译器的标志
CgoCPPFLAGS []string // cgo:C 预处理器的标志
CgoCXXFLAGS []string // cgo:C++ 编译器的标志
CgoFFLAGS []string // cgo:Fortran 编译器的标志
CgoLDFLAGS []string // cgo:链接器的标志
CgoPkgConfig []string // cgo:pkg-config 的名称
// 依赖项信息
Imports []string // 此包使用的导入路径
ImportMap map[string]string // 源导入到 ImportPath 的映射(省略标识条目)
Deps []string // 所有(递归)导入的依赖项
TestImports []string // TestGoFiles 中的导入项
XTestImports []string // XTestGoFiles 中的导入项
// 错误信息
Incomplete bool // 此包或依赖项存在错误
Error *PackageError // 加载包时出现的错误
DepsErrors []*PackageError // 加载依赖项时出现的错误
}
存储在 vendor 目录中的包报告 ImportPath,该路径包括供应商目录的路径(例如,“d/vendor/p"而不是"p”),以便 ImportPath 唯一标识给定的包副本。Imports、Deps、TestImports 和 XTestImports 列表也包含这些扩展的导入路径。有关供应商的更多信息,请参见 golang.org/s/go15vendor。
如果有错误信息,则为:
type PackageError struct {
ImportStack []string // 从命令行命名的包到此包的最短路径
Pos string // 错误的位置(如果存在,则为文件:行:列)
Err string // 错误本身
}
模块信息是一个 Module 结构,定义在下面 list -m 的讨论中。
模板函数"join"调用 strings.Join。
模板函数"context"返回构建上下文,定义为:
type Context struct {
GOARCH string // 目标架构
GOOS string // 目标操作系统
GOROOT string // Go 根目录
GOPATH string // Go 路径
CgoEnabled bool // 是否可以使用 cgo
UseAllFiles bool // 使用文件,无论是否有 +build 行、文件名
Compiler string // 在计算目标路径时要使用的编译器
BuildTags []string // 在 +build 行中匹配的构建约束
ToolTags []string // 工具链特定的构建约束
ReleaseTags []string // 当前版本兼容的版本
InstallSuffix string // 在安装目录的名称中使用的后缀
}
有关这些字段的含义的更多信息,请参阅 go/build 包的 Context 类型的文档。
-json 标志会导致以 JSON 格式而不是模板格式打印包数据。JSON 标志可以可选地与一组逗号分隔的所需字段名称一起提供,以输出这些所需字段。如果是这样,这些必需的字段将始终出现在 JSON 输出中,但其他字段可能被省略以节省计算 JSON 结构的工作。
-compiled 标志会导致 list 将 CompiledGoFiles 设置为提供给编译器的 Go 源文件。通常,这意味着它会重复列在 GoFiles 中的文件,然后还会添加通过处理 CgoFiles 和 SwigFiles 生成的 Go 代码。Imports 列表包含来自 GoFiles 和 CompiledGoFiles 的所有导入的并集。
-deps标志使列表不仅迭代命名包,还包括它们的所有依赖项。它以深度优先的后序遍历方式访问它们,这样一个包只有在所有依赖项之后才会列出。未在命令行中明确列出的包将具有DepOnly字段设置为true。
-e标志更改对错误包(无法找到或格式错误的包)的处理方式。默认情况下,list命令对于每个错误包在标准错误输出一个错误,并在通常的输出中省略这些包。使用-e标志时,list命令永远不会将错误打印到标准错误输出,并使用通常的输出处理错误包。错误的包将具有非空的ImportPath和非空的Error字段;其他信息可能存在或可能不存在(为零)。
-export标志使列表将导出字段设置为包含给定包的最新导出信息的文件的名称,并将BuildID字段设置为已编译包的构建ID。
-find标志使列表标识命名包但不解析它们的依赖项:Imports和Deps列表将为空。
-test标志不仅报告命名包,还报告它们的测试二进制文件(对于具有测试的包),以向源代码分析工具传达测试二进制文件的构造方式。测试二进制文件的报告导入路径是包的导入路径后跟一个”.test"后缀,例如"math/rand.test"。在构建测试时,有时需要特别为该测试重新构建某些依赖项(最常见的是被测试的包本身)。为特定测试二进制文件重新编译的包的报告导入路径后跟一个空格和方括号中测试二进制文件的名称,例如"math/rand math/rand.test"或"regexp [sort.test]"。ForTest字段还设置为正在测试的包的名称(在前面的示例中为"math/rand"或"sort")。
Dir,Target,Shlib,Root,ConflictDir和Export文件路径都是绝对路径。
默认情况下,GoFiles、CgoFiles等列表保存Dir中文件的名称(即相对于Dir的路径,而不是绝对路径)。当使用-compiled和-test标志时添加的生成文件是引用生成的Go源文件的缓存副本的绝对路径。虽然它们是Go源文件,但路径可能不以".go"结尾。
-m标志使列表列出模块而不是包。
当列出模块时,-f标志仍然指定应用于Go结构的格式模板,但现在是一个Module结构体:
type Module struct {
Path string // 模块路径
Query string // 对应于此版本的版本查询
Version string // 模块版本
Versions []string // 可用的模块版本
Replace *Module // 被此模块替换
Time *time.Time // 版本创建时间
Update *Module // 可用更新(使用-u)
Main bool // 是否为主模块?
Indirect bool // 模块仅由主模块间接需要
Dir string // 如果有的话,保存文件的本地副本的目录
GoMod string // 描述模块的go.mod文件的路径(如果有)
GoVersion string // 模块使用的Go版本
Retracted []string // 撤回信息(使用-retracted或-u)
Deprecated string // 废弃消息(使用-u)
Error *ModuleError // 加载模块时的错误
Origin any // 模块来源
Reuse bool // 旧模块信息的重用是安全的
}
type ModuleError struct {
Err string // 错误本身
}
GoMod文件所指的文件可能在模块目录之外,如果模块在模块缓存中或使用了-modfile标志,则是如此。
默认输出是打印模块路径,然后是版本和替换信息(如果有)。例如,“go list -m all"可能会打印:
my/main/module
golang.org/x/text v0.3.0 => /tmp/text
rsc.io/pdf v0.1.1
Module结构具有String方法,用于格式化此行输出,因此默认格式等同于-f'{{.String}}'。
请注意,当模块已被替换时,其Replace字段描述替换模块,并且如果存在,则其Dir字段设置为替换的源代码。(也就是说,如果Replace不为nil,则Dir设置为Replace.Dir,没有访问被替换源代码的方式。)
-u标志会添加有关可用升级的信息。当给定模块的最新版本比当前版本更新时,list -u会将模块的Update字段设置为有关更高版本模块的信息。如果当前版本被撤回,则list -u还将设置模块的Retracted字段。如果可用升级,则模块的String方法通过在当前版本后用括号中的较新版本进行格式化来指示可用升级。如果版本被撤回,则字符串”(撤回)“将跟随它。例如,“go list -m -u all"可能会打印:
my/main/module
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 (retracted) [v0.1.2]
(对于工具而言,‘go list -m -u -json all’ 更容易解析。)
-versions 标志会导致 list 将模块的 Versions 字段设置为该模块所有已知版本的列表,按照语义化版本控制的顺序从早到晚排序。该标志还更改默认输出格式,以模块路径为开头,后跟由空格分隔的版本列表。
-retracted 标志会导致 list 报告关于已撤销模块版本的信息。当 -retracted 与 -f 或 -json 结合使用时,Retracted 字段将被设置为一个字符串,解释为什么该版本被撤销。该字符串取自模块的 go.mod 文件中撤销指令的注释。当 -retracted 与 -versions 结合使用时,已撤销的版本会与未撤销的版本一起列出。-retracted 标志可以与或不带 -m 一起使用。
list -m 的参数被解释为模块列表,而不是包列表。主模块是包含当前目录的模块。活动模块是主模块和其依赖项。如果没有参数,list -m 会显示主模块。如果有参数,list -m 会显示由参数指定的模块。任何活动模块都可以用其模块路径来指定。特殊模式 “all” 指定所有活动模块,首先是主模块,然后是按模块路径排序的依赖项。包含 “…” 的模式指定其模块路径匹配该模式的活动模块。形式为 path@version 的查询指定该查询的结果,不限于活动模块。有关模块查询的详细信息,请参见 ‘go help modules’。
模板函数 “module” 接受一个字符串参数,必须是模块路径或查询,并将指定的模块返回为 Module 结构体。如果发生错误,结果将是一个带有非空错误字段的 Module 结构体。
使用 -m 时,-reuse=old.json 标志接受以前 ‘go list -m -json’ 调用的 JSON 输出文件名,该调用具有相同的修改器标志集(例如 -u、-retracted 和 -versions)。go 命令可以使用此文件确定自上次调用以来模块未更改,并避免重新下载有关它的信息。未重新下载的模块将通过将 Reuse 字段设置为 true 在新输出中标记。通常,模块缓存会自动提供此类重用;-reuse 标志可用于不保留模块缓存的系统。
有关构建标志的更多信息,请参见 ‘go help build’。
有关指定包的更多信息,请参见 ‘go help packages’。
有关模块的更多信息,请参见 https://golang.org/ref/mod。
模块维护
go mod 提供了对模块操作的访问。
请注意,对模块的支持内置于所有 go 命令中,而不仅仅是 ‘go mod’。例如,日常添加、删除、升级和降级依赖关系应使用 ‘go get’ 完成。有关模块功能的概述,请参阅 ‘go help modules’。
用法:
go mod <command> [arguments]
命令如下:
download 将模块下载到本地缓存
edit 从工具或脚本编辑 go.mod
graph 打印模块依赖关系图
init 在当前目录中初始化新模块
tidy 添加缺少的模块并删除未使用的模块
vendor 制作依赖关系的供应商副本
verify 验证依赖项具有预期的内容
why 解释需要哪些包或模块
使用 “go help mod
将模块下载到本地缓存
用法:
go mod download [-x] [-json] [-reuse=old.json] [modules]
download 命令会下载指定的模块,可以是选择主模块依赖项的模块模式,也可以是形式为 path@version 的模块查询。
如果没有指定参数,则 download 命令适用于构建和测试主模块中的包所需的模块:如果主模块处于 ‘go 1.17’ 或更高版本,则为主模块明确要求的模块,否则为所有必需的传递模块(对于 ‘go 1.16’ 或更低版本)。
在普通执行期间,go 命令将自动根据需要下载模块。“go mod download” 命令主要用于预先填充本地缓存或计算 Go 模块代理的答案。
默认情况下,download 不会向标准输出写入任何内容。它可能会将进度消息和错误打印到标准错误。
使用 -json 标志将导致 download 向标准输出打印一系列 JSON 对象,描述每个已下载的模块(或失败),对应于此 Go 结构体:
type Module struct {
Path string // 模块路径
Query string // 版本查询,对应于此版本
Version string // 模块版本
Error string // 加载模块时出现的错误
Info string // 缓存的 .info 文件的绝对路径
GoMod string // 缓存的 .mod 文件的绝对路径
Zip string // 缓存的 .zip 文件的绝对路径
Dir string // 缓存的源根目录的绝对路径
Sum string // 路径、版本的校验和(如 go.sum)
GoModSum string // go.mod 的校验和(如 go.sum)
Origin any // 模块来源的证明
Reuse bool // 重用旧模块信息是安全的
}
-reuse 标记接受包含之前的 ‘go mod download -json’ 调用的 JSON 输出的文件名。go 命令可以使用此文件确定模块是否自上次调用以来未更改并避免重新下载。不重新下载的模块将通过将 Reuse 字段设置为 true 来标记在新输出中。通常模块缓存会自动提供此类重用;-reuse 标记可以在不保留模块缓存的系统上很有用。
-x 标记会导致 download 打印出执行的命令。
有关"go mod download"的更多信息,请参见 https://golang.org/ref/mod#go-mod-download。
有关版本查询的更多信息,请参见 https://golang.org/ref/mod#version-queries。
从工具或脚本编辑 go.mod
用法:
go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
edit 提供了一个命令行界面,用于编辑 go.mod,主要供工具或脚本使用。它只读取 go.mod,不会查找有关所涉及的模块的信息。默认情况下,edit 读取和写入主模块的 go.mod 文件,但在编辑标记后可以指定不同的目标文件。
编辑标记指定一系列编辑操作。
-fmt 标记重新格式化 go.mod 文件而不进行其他更改。此重新格式化也隐含在使用或重写 go.mod 文件的任何其他修改中。只有在未指定其他标记时(例如 ‘go mod edit -fmt’)才需要此标记。
-module 标记更改模块的路径(go.mod 文件的模块行)。
-require=path@version 和 -droprequire=path 标志添加和删除给定模块路径和版本的要求。请注意,-require 覆盖路径上的所有现有要求。这些标志主要用于了解模块图的工具。用户应该优先使用 ‘go get path@version’ 或 ‘go get path@none’,这些命令会根据其他模块的约束条件进行必要的 go.mod 调整。
-exclude=path@version 和 -dropexclude=path@version 标志添加和删除给定模块路径和版本的排除项。请注意,如果该排除项已存在,则 -exclude=path@version 不起作用。
-replace=old[@v]=new[@v] 标志添加给定模块路径和版本对的替换项。如果在 old@v 中省略 @v,则添加左侧没有版本的替换项,该替换项适用于该旧模块路径的所有版本。如果在 new@v 中省略 @v,则新路径应为本地模块根目录,而不是模块路径。请注意,-replace 覆盖了 old[@v] 的任何冗余替换项,因此省略 @v 将删除特定版本的现有替换项。
-dropreplace=old[@v] 标志删除给定模块路径和版本对的替换项。如果省略 @v,则删除左侧没有版本的替换项。
-retract=version 和 -dropretract=version 标志添加和删除给定版本的撤销。版本可以是单个版本,例如"v1.2.3”,也可以是封闭间隔,例如”[v1.1.0,v1.1.9]"。请注意,如果该撤回已经存在,则 -retract=version 不起作用。
-require、-droprequire、-exclude、-dropexclude、-replace、-dropreplace、-retract 和 -dropretract 编辑标志可以重复使用,更改按给定的顺序应用。
-go=version 标志设置预期的 Go 语言版本。
-print 标志以其文本格式打印最终的 go.mod,而不是将其写回 go.mod。
-json 标志以 JSON 格式打印最终的 go.mod 文件,而不是将其写回 go.mod。JSON 输出对应于这些 Go 类型:
type Module struct {
Path string
Version string
}
type GoMod struct {
Module ModPath
Go string
Require []Require
Exclude []Module
Replace []Replace
Retract []Retract
}
type ModPath struct {
Path string
Deprecated string
}
type Require struct {
Path string
Version string
Indirect bool
}
type Replace struct {
Old Module
New Module
}
type Retract struct {
Low string
High string
Rationale string
}
Retract 条目表示单个版本(而非区间),“Low” 和 “High” 字段将设置为相同的值。
请注意,这仅描述 go.mod 文件本身,而不是间接引用的其他模块。要查看可用于构建的完整模块集,请使用 ‘go list -m -json all’。
edit 还提供了 -C、-n 和 -x 构建标志。
有关 ‘go mod edit’ 的更多信息,请参见 https://golang.org/ref/mod#go-mod-edit。
打印模块需求图
用法:
go mod graph [-go=version] [-x]
graph 以文本形式打印模块需求图(已应用替换)。输出中的每一行都有两个空格分隔的字段:模块和其要求之一。除主模块外,每个模块都被标识为 path@version 格式的字符串,而主模块没有 @version 后缀。
-go 标志导致 graph 报告按照给定的 Go 版本加载的模块图,而不是 go.mod 文件中 ‘go’ 指令指示的版本。
-x 标志导致 graph 打印 graph 执行的命令。
有关 ‘go mod graph’ 的更多信息,请参见 https://golang.org/ref/mod#go-mod-graph。
在当前目录中初始化新模块
用法:
go mod init [module-path]
init 在当前目录中初始化并写入新的 go.mod 文件,实际上创建一个以当前目录为根的新模块。go.mod 文件不能已经存在。
init 接受一个可选参数,新模块的模块路径。如果省略模块路径参数,则 init 将尝试使用 .go 文件中的导入注释、供应商工具配置文件(如 Gopkg.lock)和当前目录(如果在 GOPATH 中)来推断模块路径。
如果存在供应商工具的配置文件,则 init 将尝试从其导入模块要求。
有关 ‘go mod init’ 的更多信息,请参见 https://golang.org/ref/mod#go-mod-init。
添加缺失和删除未使用的模块
用法:
go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]
tidy 确保 go.mod 与模块中的源代码匹配。它添加了构建当前模块的包和依赖项所需的任何缺失模块,并删除未提供任何相关包的未使用模块。它还添加任何缺失的条目到 go.sum,并删除任何不必要的条目。
-v 标志导致 tidy 打印有关已删除模块的信息到标准错误。
-e 标志导致 tidy 尝试在加载包时遇到错误时继续进行。
-go 标志会导致 tidy 更新 go.mod 文件中的 ‘go’ 指令到给定的版本,这可能会改变哪些模块依赖项在 go.mod 文件中作为显式要求保留。(Go 版本 1.17 及更高版本会保留更多的要求以支持懒惰模块加载。)
-compat 标志保留所需的任何附加校验和,以便从指定的主 Go 发布版本成功加载模块图形,并且如果该 ‘go’ 命令版本会从不同模块版本加载任何已导入的包,则会导致 tidy 出错。默认情况下,tidy 表现得好像将 -compat 标志设置为 go.mod 文件中指示的版本的前一个版本。
-x 标志会导致 tidy 打印下载命令执行的命令。
有关 ‘go mod tidy’ 的更多信息,请参见 https://golang.org/ref/mod#go-mod-tidy。
创建依赖项的副本以供vendor
用法:
go mod vendor [-e] [-v] [-o outdir]
vendor 重置主模块的供应商目录,以包括构建和测试所有主模块包所需的所有包。它不包括供应商软件包的测试代码。
-v 标志导致供应商将供应商的模块和包名称打印到标准错误输出。
-e 标志会导致供应商尝试在加载包时遇到错误后继续运行。
-o 标志会导致供应商在给定路径处创建供应商目录,而不是在 “vendor” 中。go 命令只能在模块根目录中命名为 “vendor” 的供应商目录,因此该标志主要对其他工具有用。
有关 ‘go mod vendor’ 的更多信息,请参见 https://golang.org/ref/mod#go-mod-vendor。
验证依赖项是否具有预期内容
用法:
go mod verify
verify 检查当前模块的依赖项(存储在本地下载的源缓存中)是否在下载后已被修改。如果所有模块都未被修改,则 verify 打印 “all modules verified."。否则它会报告哪些模块已被更改,并导致 ‘go mod’ 退出并显示一个非零状态码。
有关"go mod verify"的更多信息,请参见 https://golang.org/ref/mod#go-mod-verify。
解释为什么需要包或模块
用法:
go mod why [-m] [-vendor] packages...
why 显示从主模块到每个列出的包的导入图中的最短路径。如果指定了 -m 标志,则 why 将参数视为模块列表,并为每个模块找到一个路径到任何包。
默认情况下,why 查询与 “go list all” 匹配的包图,其中包括可访问包的测试。-vendor 标志使 why 排除依赖项的测试。
输出是一系列段落,每个包或模块名称在命令行上都有一个段落,段落之间用空行分隔。每个段落以注释行 “# package” 或 “# module” 开头,给出目标包或模块。随后的行以一个包为一行,给出了导入图中的路径。如果从主模块中没有引用该包或模块,则段落将显示一个括号注释,指出这一点。
例如:
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
$
有关"go mod why"的更多信息,请参见https://golang.org/ref/mod#go-mod-why。
工作区维护
work 提供了对工作区进行操作的访问。
请注意,对于工作区的支持内置于许多其他命令中,而不仅仅是 ‘go work’。
有关工作区的信息,请参见 ‘go help modules’。工作区是 Go 模块系统的一部分。
有关工作区的深入参考,请参见 https://go.dev/ref/mod#workspaces。
有关工作区的入门教程,请参见 https://go.dev/doc/tutorial/workspaces。
工作区由一个 go.work 文件指定,该文件使用 “use” 指令指定一组模块目录。这些模块由 go 命令用作构建和相关操作的根模块。未指定要使用的模块的工作区无法用于从本地模块进行构建。
go.work 文件是面向行的。每行包含一个指令,由关键字和参数组成。例如:
go 1.18
use ../foo/bar
use ./baz
replace example.com/foo v1.2.3 => example.com/bar v1.4.5
前导关键字可以从相邻行中分离出来以创建块,就像 Go 导入一样。
use (
../foo/bar
./baz
)
use 指令指定要包含在工作区主模块集中的模块。use 指令的参数是包含该模块的 go.mod 文件的目录。
go 指令指定了文件编写的 Go 版本。可能有将来的更改,这些更改可能由该版本控制工作区的语义,但是目前指定的版本没有影响。
replace 指令具有与 go.mod 文件中的 replace 指令相同的语法,并优先于 go.mod 文件中的替换。它主要用于覆盖不同工作区模块中的冲突替换。
要确定 go 命令是否在工作区模式下运行,请使用 “go env GOWORK” 命令。这将指定正在使用的工作区文件。
用法:
go work <command> [arguments]
命令为:
edit 从工具或脚本编辑 go.work
init 初始化工作区文件
sync 同步工作区构建列表到模块
use 向工作区文件中添加模块
有关命令的更多信息,请使用 “go help work
从工具或脚本编辑 go.work
用法:
go work edit [editing flags] [go.work]
edit 提供了一个命令行界面用于编辑 go.work 文件,主要供工具或脚本使用。它只读取 go.work 文件,不会查找有关模块的信息。如果未指定文件,则 Edit 会在当前目录和其父目录中查找 go.work 文件。
editing标志指定一系列编辑操作。
-fmt 标志重新格式化 go.work 文件,而不做其他更改。任何使用或重写 go.mod 文件的其他修改都会隐含此重新格式化。只有在没有指定其他标志的情况下才需要此标志,例如 go work edit -fmt。
-use=path 和 -dropuse=path 标志向 go.work 文件的模块目录集添加和删除 use 指令。
-replace=old[@v]=new[@v] 标志添加给定模块路径和版本对的替换。如果省略 old@v 中的 @v,则会添加左侧没有版本的替换,这适用于旧模块路径的所有版本。如果省略 new@v 中的 @v,则新路径应为本地模块根目录,而不是模块路径。请注意,-replace 会覆盖 old[@v] 的任何冗余替换,因此省略 @v 将删除特定版本的现有替换。
-dropreplace=old[@v] 标志删除给定模块路径和版本对的替换。如果省略 @v,则会删除左侧没有版本的替换。
-use、-dropuse、-replace 和 -dropreplace 编辑标志可以重复,更改按给定的顺序应用。
-go=version 标志设置期望的 Go 语言版本。
-print 标志以文本格式打印最终的 go.work,而不是将其写回 go.mod。
-json 标志以 JSON 格式打印最终的 go.work 文件,而不是将其写回 go.mod。JSON 输出对应于这些 Go 类型:
type GoWork struct {
Go string
Use []Use
Replace []Replace
}
type Use struct {
DiskPath string
ModulePath string
}
type Replace struct {
Old Module
New Module
}
type Module struct {
Path string
Version string
}
有关更多信息,请参见工作区参考:Go模块参考中的工作区。
初始化工作区文件
用法:
go work init [moddirs]
init 在当前目录中初始化并编写新的 go.work 文件,实际上创建了一个新的工作区。
go work init 可选地接受工作区模块的路径作为参数。如果省略参数,则将创建一个没有模块的空工作区。
每个路径参数都会添加到 go.work 文件的 use 指令中。当前的 Go 版本也将在 go.work 文件中列出。
有关更多信息,请参见工作区参考:Go模块参考中的工作区。
同步工作区的构建清单到模块
用法:
go work sync
sync命令将工作区的构建清单同步回工作区的模块
工作区的构建清单是所有(传递)依赖模块的版本集,这些依赖模块用于在工作区进行构建操作。 go work sync使用最小版本选择算法生成该构建清单,然后将这些版本与工作区指定的每个模块(使用指令)同步。
如果依赖模块的版本与构建清单的版本不同,则按顺序将工作区模块中指定的每个依赖模块升级到构建清单中的版本。请注意,最小版本选择保证构建清单中每个模块的版本始终相同或更高于每个工作区模块中的版本。
有关更多信息,请参见工作区参考:Go模块参考中的工作区。
将模块添加到工作区文件
用法:
go work use [-r] moddirs
use提供了一个命令行界面,用于将目录(可选地进行递归搜索)添加到go.work文件中。
如果go.work文件中存在,那么每个命令行上列出的参数目录都将在go.work文件中添加一个use指令,否则将从go.work文件中删除。
-r标志在参数目录中递归搜索模块,并且use命令操作方式与指定每个目录作为参数相同:即对于存在的目录将添加use指令,并且对于不存在的目录将删除use指令。
有关更多信息,请参见工作区参考:Go模块参考中的工作区。
编译并运行Go程序
用法:
go run [build flags] [-exec xprog] package [arguments...]
run编译并运行指定的Go 主包。通常,该程序被指定为来自单个目录的一系列.go源文件的列表,但也可以是导入路径、文件系统路径或与单个已知程序匹配的模式,例如"go run .“或"go run my/cmd”。
如果包参数有版本后缀(如@latest或@v1.0.0),“go run"将在模块感知模式下构建程序,忽略当前目录或任何父目录中的go.mod文件。这对于运行程序而不影响主模块的依赖项非常有用。
如果包参数没有版本后缀,“go run"可以在模块感知模式或GOPATH模式下运行,具体取决于GO111MODULE环境变量和go.mod文件的存在性。有关详细信息,请参见"go help modules”。如果启用了模块感知模式,“go run"将在主模块的上下文中运行。
默认情况下,“go run"直接运行已编译的二进制文件:“a.out arguments…"。如果给出了”-exec"标志,“go run"将使用xprog调用二进制文件:
'xprog a.out arguments...'.
如果未给出”-exec"标志,且GOOS或GOARCH与系统默认值不同,并且在当前搜索路径中可以找到一个名为”go_$GOOS_$GOARCH_exec“的程序,例如"go_js_wasm_exec a.out arguments…",则"go run"将使用该程序调用二进制文件。这使得可以使用模拟器或其他执行方法来执行跨编译程序。
默认情况下,“go run"编译二进制文件时不会生成调试器使用的信息,以减少构建时间。要在二进制文件中包含调试器信息,请使用"go build”。
run的退出状态不是已编译的二进制文件的退出状态。
有关构建标志的更多信息,请参见"go help build”。有关指定软件包的更多信息,请参见"go help packages”。
另请参见:go build。
测试包
用法:
go test [build/test flags] [packages] [build/test flags & test binary flags]
‘go test’ 自动测试由导入路径指定的包。它以以下格式打印测试结果的摘要:
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
之后是每个失败包的详细输出。
‘go test’ 重新编译每个包及其与文件名匹配的 “*_test.go” 文件。这些附加文件可以包含测试函数、基准函数、模糊测试和示例函数。有关更多信息,请参见 ‘go help testfunc’。每个列出的包都会导致执行一个单独的测试二进制文件。以”_"(包括”_test.go")或”.“开头的文件将被忽略。
声明具有后缀 “_test” 的包的测试文件将被编译为单独的包,然后与主测试二进制文件链接和运行。
go 工具将忽略名为 “testdata” 的目录,使其可用于保存测试所需的辅助数据。
在构建测试二进制文件的过程中,go test 运行 go vet 命令,对包及其测试源文件进行静态分析,以识别重要的问题。如果 go vet 发现任何问题,go test 将报告这些问题并不运行测试二进制文件。仅使用默认的一组高置信度的 go vet 检查,包括 ‘atomic’、‘bool’、‘buildtags’、’errorsas’、‘ifaceassert’、’nilfunc’、‘printf’ 和 ‘stringintconv’。您可以通过 “go doc cmd/vet” 查看这些和其他 vet 测试的文档。要禁用 go vet 的运行,请使用 -vet=off 标志。要运行所有检查,请使用 -vet=all 标志。
所有测试输出和摘要行都会打印到 go 命令的标准输出中,即使测试已将它们打印到自己的标准错误中。(go 命令的标准错误用于打印构建测试时的错误。)
go test 有两种不同的运行模式:
第一种被称为本地目录模式,当 go test 未使用包参数调用时(例如 ‘go test’ 或 ‘go test -v’),它将编译当前目录中找到的包源和测试,然后运行生成的测试二进制文件。在这种模式下,禁用缓存(下面讨论)。包测试完成后,go test 打印一个总结行,显示测试状态(‘ok’ 或 ‘FAIL’)、包名和运行时间。
第二种情况称为包列表模式,当使用显式包参数调用go test时发生(例如’go test math’、‘go test ./…‘和’go test .’)。在此模式下,go test编译并测试命令行上列出的每个包。如果包测试通过,go test仅打印最终的"ok"摘要行。如果包测试失败,go test会打印完整的测试输出。如果使用-bench或-v标志调用,则为了显示请求的基准结果或详细日志记录,go test即使对于通过的包测试也会打印完整输出。在列出的所有包的包测试完成并输出后,如果任何包测试失败,go test将打印最终的"FAIL"状态。
仅在包列表模式下,go test会缓存成功的包测试结果,以避免重复运行测试。当测试结果可以从缓存中恢复时,go test会重新显示先前的输出,而不是再次运行测试二进制文件。当发生这种情况时,go test会在摘要行中的经过时间的位置打印”(cached)"。
缓存匹配的规则是运行涉及相同的测试二进制文件,并且命令行上的标志完全来自"可缓存"测试标志的受限集合,这些标志被定义为-benchtime、-cpu、-list、-parallel、-run、-short、-timeout、-failfast和-v。如果go test运行有任何测试或非测试标志在此集合之外,结果将不会被缓存。要禁用测试缓存,请使用除可缓存标志之外的任何测试标志或参数。显式禁用测试缓存的惯用方法是使用-count = 1。在包的源根目录(通常是$GOPATH)中打开文件或仅查看环境变量的测试将只匹配未来运行的情况,其中文件和环境变量未更改。缓存的测试结果被视为根本没有执行时间,因此成功的包测试结果将被缓存和重复使用,无论-timeout设置如何。
除了构建标志之外,‘go test’本身处理的标志为:
-args
将命令行剩余部分(-args后面的所有内容)传递给测试二进制文件,
未经解释且不变。由于此标志消耗了命令行的剩余部分,
因此包列表(如果存在)必须出现在此标志之前。
-c
编译测试二进制文件到pkg.test,
但不运行它(其中pkg是包导入路径的最后一个元素)。
可以使用-o标志更改文件名。
-exec xprog
使用xprog运行测试二进制文件。
行为与"go run"相同。有关详细信息,请参见'go help run'。
-json
将测试输出转换为适用于自动化处理的JSON格式。
有关编码细节,请参阅"go doc test2json"。
-o file
将测试二进制文件编译到指定文件中。
测试仍然运行(除非指定了-c或-i)。
测试二进制文件还接受控制测试执行的标志;这些标志也可以由"go test"访问。有关详细信息,请参阅"go help testflag"。
有关构建标志的更多信息,请参阅"go help build"。有关指定软件包的更多信息,请参阅"go help packages"。
另请参见:go build、go vet。
运行指定的go工具
用法:
go tool [-n] command [args...]
tool运行由参数标识的go工具命令。如果没有参数,则打印已知工具列表。
-n标志导致tool打印将要执行的命令,但不执行它。
有关每个工具命令的详细信息,请参见"go doc cmd/
打印Go版本
用法:
go version [-m] [-v] [file ...]
version 打印Go二进制文件的构建信息。
go version 报告用于构建每个命名文件的Go版本。
如果命令行中没有命名文件,则go version打印自己的版本信息。
如果指定了目录,则go version递归地遍历该目录,寻找已知的Go二进制文件并报告它们的版本。默认情况下,go version不会报告目录扫描期间发现的无法识别的文件。-v标志会导致其报告无法识别的文件。
-m标志使go version在可能的情况下打印每个文件的嵌入式模块版本信息。在输出中,模块信息由版本行以下的多行组成,每行前面都有一个制表符。
另请参见:go doc runtime/debug.BuildInfo。
报告软件包中的可能错误
用法:
go vet [-C dir] [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
vet在由导入路径命名的软件包上运行go vet命令。
有关vet及其标志的更多信息,请参见"go doc cmd/vet"。有关指定软件包的更多信息,请参见"go help packages"。有关检查器及其标志的列表,请参见"go tool vet help"。有关特定检查器(例如’printf’)的详细信息,请参见"go tool vet help printf"。
-C标志在运行"go vet"命令之前更改到dir。-n标志打印将要执行的命令。-x标志在执行命令时打印命令。
-vettool=prog标志选择具有替代或附加检查的不同分析工具。例如,可以使用以下命令构建和运行"shadow"分析器:
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest
go vet -vettool=$(which shadow)
go vet支持的构建标志是控制软件包解析和执行的标志,例如-n、-x、-v、-tags和-toolexec。有关这些标志的更多信息,请参见"go help build"。
另请参见:go fmt、go fix。
构建约束条件
构建约束条件(也称为构建标记)是决定一个文件是否应该被包含在包中的条件。构建约束条件是由以下行注释给出的:
//go:build
约束条件可以出现在任何类型的源文件(不仅仅是 Go 文件),但它们必须出现在文件的顶部附近,只有空行和其他行注释可以在它们之前。这些规则意味着在 Go 文件中,构建约束条件必须出现在包语句之前。
为了区分构建约束条件和包文档,构建约束条件应该在空行后跟随一个空行。
构建约束条件注释将被视为一个表达式,该表达式由 ||、&& 和 ! 运算符以及括号组合而成的构建标记组成。这些运算符的含义与 Go 中相同。
例如,以下构建约束条件约束了一个文件只有在满足"linux"和"386"约束条件,或者在满足"darwin"约束条件且不满足"cgo"约束条件时才能构建:
//go:build (linux && 386) || (darwin && !cgo)
一个文件如果有多于一个 //go:build 行注释,会引发错误。
在特定的构建过程中,以下构建标记将被满足:
-
目标操作系统,由 runtime.GOOS 拼写,使用 GOOS 环境变量设置。
-
目标架构,由 runtime.GOARCH 拼写,使用 GOARCH 环境变量设置。
-
任何架构特性,采用 GOARCH.feature 的形式(例如,“amd64.v2”),如下所述。
-
如果 GOOS 是 Unix 或类 Unix 系统,则为"unix"。
-
所使用的编译器,可以是"gc"或"gccgo"。
-
如果支持 cgo 命令(请参阅"go help environment"中的 CGO_ENABLED),则为"cgo"。
-
每个 Go 主要版本的术语,直到当前版本为止:“go1.1"从 Go 1.1 开始,“go1.12"从 Go 1.12 开始,以此类推。
-
通过 -tags 标记提供的任何其他标记(请参阅"go help build”)。
beta 版本或小版本没有单独的构建标记。
如果文件名在去掉扩展名和可能的 _test 后,匹配以下任一模式:
*_GOOS
*_GOARCH
*_GOOS_GOARCH
(例如:source_windows_amd64.go),其中 GOOS 和 GOARCH 分别表示任何已知的操作系统和架构值,则该文件被认为具有需要这些术语的隐式构建约束条件(除了文件中的任何显式约束条件)。
使用GOOS=android与GOOS=linux相匹配,以及android标记和文件。
使用GOOS=illumos与GOOS=solaris相匹配,并在illumos标记和文件上进行了补充。
使用GOOS=ios与GOOS=darwin相匹配,并在ios标记和文件上进行了补充。
已定义的架构特性构建标签为:
- 对于GOARCH=386,GO386=387和GO386=sse2,分别设置386.387和386.sse2构建标签。
- 对于GOARCH=amd64,GOAMD64=v1、v2和v3对应于amd64.v1、amd64.v2和amd64.v3特性构建标签。
- 对于GOARCH=arm,GOARM=5、6和7对应于arm.5、arm.6和arm.7特性构建标签。
- 对于GOARCH=mips或mipsle,GOMIPS=hardfloat和softfloat对应于mips.hardfloat和mips.softfloat(或mipsle.hardfloat和mipsle.softfloat)特性构建标签。
- 对于GOARCH=mips64或mips64le,GOMIPS64=hardfloat和softfloat对应于mips64.hardfloat和mips64.softfloat(或mips64le.hardfloat和mips64le.softfloat)特性构建标签。
- 对于GOARCH=ppc64或ppc64le,GOPPC64=power8、power9和power10对应于ppc64.power8、ppc64.power9和ppc64.power10(或ppc64le.power8、ppc64le.power9和ppc64le.power10)特性构建标签。
- 对于GOARCH=wasm,GOWASM=satconv和signext对应于wasm.satconv和wasm.signext特性构建标签。
对于GOARCH=amd64、arm、ppc64和ppc64le,特定特性级别也会设置先前所有级别的特性构建标签。例如,GOAMD64=v2设置了amd64.v1和amd64.v2特性标志。这确保使用v2特性的代码在引入GOAMD64=v4时继续编译。处理特定特性级别的缺失的代码应使用否定:
//go:build !amd64.v2
为了使文件不被考虑进行任何构建:
//go:build ignore
(任何其他未满足的单词都可以工作,但"ignore"是常规的。)
仅在使用cgo时并且仅在Linux和OS X上构建文件:
//go:build cgo && (linux || darwin)
这样的文件通常与实现其他系统的默认功能的另一个文件配对,该文件将带有以下限制:
//go:build !(cgo && (linux || darwin))
命名为dns_windows.go的文件将导致仅在为Windows构建包时包含它;同样,命名为math_386.s的文件将仅在为32位x86构建包时包含它。
Go版本1.16及更早版本使用不同的构建限制语法,使用”// +build"前缀。在遇到旧语法时,gofmt命令将添加等效的//go:build约束。
构建模式
‘go build’ 和 ‘go install’ 命令可以使用 -buildmode 参数指定要构建哪种类型的目标文件。目前支持的值为:
-buildmode=archive
将列出的非 main 包构建为 .a 文件。名为 main 的包将被忽略。
-buildmode=c-archive
将列出的 main 包以及它导入的所有包构建为 C 归档文件。
唯一可调用的符号将是那些使用 cgo 的 //export 注释导出的函数。
需要列出一个 main 包。
-buildmode=c-shared
将列出的 main 包以及它导入的所有包构建为 C 共享库。
唯一可调用的符号将是那些使用 cgo 的 //export 注释导出的函数。
需要列出一个 main 包。
-buildmode=default
列出的 main 包构建为可执行文件,
列出的非 main 包构建为 .a 文件(默认行为)。
-buildmode=shared
将所有列出的非 main 包组合成一个共享库,
将在使用 -linkshared 选项进行构建时使用。
名为 main 的包将被忽略。
-buildmode=exe
将列出的 main 包及其导入的所有内容构建为可执行文件。
名为 main 以外的包将被忽略。
-buildmode=pie
将列出的 main 包及其导入的所有内容构建为位置无关可执行文件(PIE)。
名为 main 以外的包将被忽略。
-buildmode=plugin
将列出的 main 包以及它们导入的所有包构建为 Go 插件。
名为 main 以外的包将被忽略。
在 AIX 上,当链接使用 -buildmode=c-archive 构建的 Go 归档文件的 C 程序时,必须向 C 编译器传递 -Wl,-bnoobjreorder。
调用 Go 和 C 之间的交互
调用 Go 和 C/C++ 代码有两种不同的方法。
第一种是 cgo 工具,它是 Go 发行版的一部分。有关如何使用它的信息,请参阅 cgo 文档(go doc cmd/cgo)。
第二种是 SWIG 程序,它是一种用于不同语言间接口的通用工具。关于 SWIG 的信息请参见 http://swig.org/。在运行 go build 时,任何具有 .swig 扩展名的文件都将被传递给 SWIG。任何具有 .swigcxx 扩展名的文件都将被传递给带有 -c++ 选项的 SWIG。
当使用 cgo 或 SWIG 时,go build 将任何 .c、.m、.s、.S 或 .sx 文件传递给 C 编译器,并将任何 .cc、.cpp、.cxx 文件传递给 C++ 编译器。CC 或 CXX 环境变量可以设置以确定要使用的 C 或 C++ 编译器。
构建和测试缓存
go 命令缓存构建输出以便将来重复使用。缓存数据的默认位置是当前操作系统的标准用户缓存目录中名为 go-build 的子目录。设置 GOCACHE 环境变量将覆盖此默认设置,并且运行 ‘go env GOCACHE’ 将打印当前缓存目录。
go 命令定期删除未经常用的缓存数据。运行 ‘go clean -cache’ 将删除所有缓存的数据。
构建缓存正确计算 Go 源文件、编译器、编译器选项等更改:在典型用法中不需要显式清除缓存。但是,构建缓存不会检测使用 cgo 导入的 C 库的更改。如果您对系统上的 C 库进行了更改,则需要显式清除缓存,否则使用 -a 构建标志(请参阅 ‘go help build’)强制重建依赖于更新的 C 库的包。
go 命令还会缓存成功的软件包测试结果。有关详细信息,请参见 ‘go help test’。运行 ‘go clean -testcache’ 将删除所有缓存的测试结果(但不会删除缓存的构建结果)。
go 命令还会缓存用于 ‘go test -fuzz’ 进行模糊测试的值,特别是将扩展代码覆盖率的值传递给模糊函数。这些值不用于常规构建和测试,但是它们存储在构建缓存的子目录中。运行 ‘go clean -fuzzcache’ 将删除所有缓存的模糊值。这可能会使模糊测试在短时间内变得不那么有效。
GODEBUG环境变量可以启用有关缓存状态的调试信息:
GODEBUG=gocacheverify=1会导致go命令绕过使用任何缓存条目,而是重新构建所有内容并检查结果是否与现有的缓存条目匹配。
GODEBUG=gocachehash=1会导致go命令打印用于构建缓存查找键的所有内容哈希的输入。输出很多,但可用于调试缓存。
GODEBUG=gocachetest=1会导致go命令打印有关是否重用缓存测试结果的详细信息。
环境变量
go命令及其调用的工具会查询环境变量以进行配置。如果环境变量未设置,则go命令将使用合理的默认设置。要查看变量<NAME>的有效设置,请运行’go env <NAME>’。要更改默认设置,请运行’go env -w <NAME>=<VALUE>’。使用’go env -w’更改的默认值会记录在一个Go环境配置文件中,该文件存储在每个用户配置目录中,该目录由os.UserConfigDir报告。配置文件的位置可以通过设置环境变量GOENV来更改,‘go env GOENV’打印有效位置,但’go env -w’无法更改默认位置。有关详细信息,请参见’go help env’。
通用环境变量:
GO111MODULE
控制go命令运行在模块感知模式还是GOPATH模式下。
可能的取值为"off","on"或"auto"。
详见https://golang.org/ref/mod#mod-commands。
GCCGO
运行'go build -compiler=gccgo'所用的gccgo命令。
GOARCH
编译代码的架构或处理器。例如,amd64,386,arm,ppc64。
GOBIN
'go install'命令安装命令的目录。
GOCACHE
go命令存储缓存信息以便于在未来的构建中重复使用的目录。
GOMODCACHE
go命令存储已下载模块的目录。
GODEBUG
启用各种调试功能。详见'go doc runtime'。
GOENV
Go环境配置文件的位置。
不能使用'go env -w'设置。
将环境变量GOENV设置为"off"禁用使用默认配置文件。
GOFLAGS
要默认应用的一系列空格分隔的-flag=value标志设置,
当当前命令已知该标志时。
每个条目必须是一个独立的标志。
因为条目是以空格分隔的,所以标志值不能包含空格。
在命令行中列出的标志将在此列表之后应用,因此会覆盖它。
GOINSECURE
用逗号分隔的模块路径前缀的通配符模式(使用Go的path.Match语法),
它们始终以不安全的方式获取。
仅适用于直接获取的依赖项。
GOINSECURE不会禁用校验和数据库验证。
GOPRIVATE或GONOSUMDB可用于实现该功能。
GOOS
编译代码的操作系统。例如,linux,darwin,windows,netbsd。
GOPATH
更多详见'go help gopath'。
GOPROXY
Go 模块代理的 URL。
有关详细信息,请参见
https://golang.org/ref/mod#environment-variables
和 https://golang.org/ref/mod#module-proxy。
GOPRIVATE,GONOPROXY,GONOSUMDB
逗号分隔的模块路径前缀的通配符列表(使用 Go 的 path.Match 语法),
它们应始终直接获取,或不应与校验和数据库进行比较。
请参见 https://golang.org/ref/mod#private-modules。
GOROOT
Go 树的根目录。
GOSUMDB
要使用的校验和数据库的名称及其公钥和 URL(可选)。
请参见 https://golang.org/ref/mod#authenticating。
GOTMPDIR
Go 命令将写入临时源文件、包和二进制文件的目录。
GOVCS
列出可能与匹配服务器一起使用的版本控制命令。请参见 'go help vcs'。
GOWORK
在模块感知模式下,使用给定的 go.work 文件作为工作空间文件。
默认情况下或当 GOWORK 为 "auto" 时,
go 命令会在当前目录及包含目录中搜索名为 go.work 的文件,
直到找到为止。
如果找到有效的 go.work 文件,则所指定的模块将共同用作主要模块。
如果 GOWORK 为 "off",或者在 "auto" 模式下未找到 go.work 文件,
则禁用工作空间模式。
用于与 cgo 一起使用的环境变量:
AR
在使用 gccgo 编译器进行构建时,用于操作库档案的命令。默认值为 'ar'。
CC
用于编译 C 代码的命令。
CGO_ENABLED
是否支持 cgo 命令。为 0 或 1。
CGO_CFLAGS
cgo 在编译 C 代码时将传递给编译器的标志。
CGO_CFLAGS_ALLOW
指定允许在 #cgo CFLAGS 源代码指令中出现的其他标志的正则表达式。
不适用于 CGO_CFLAGS 环境变量。
CGO_CFLAGS_DISALLOW
指定必须禁止出现在 #cgo CFLAGS 源代码指令中的标志的正则表达式。
不适用于 CGO_CFLAGS 环境变量。
CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
与 CGO_CFLAGS、CGO_CFLAGS_ALLOW 和 CGO_CFLAGS_DISALLOW 类似,
但用于 C 预处理器。
CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
but for the C++ compiler.
与 CGO_CFLAGS、CGO_CFLAGS_ALLOW 和 CGO_CFLAGS_DISALLOW 类似,
但是用于 C++ 编译器。
CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
与 CGO_CFLAGS、CGO_CFLAGS_ALLOW 和 CGO_CFLAGS_DISALLOW 类似,
但是用于 Fortran 编译器。
CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
与 CGO_CFLAGS、CGO_CFLAGS_ALLOW 和 CGO_CFLAGS_DISALLOW 类似,
但是用于链接器。
CXX
用于编译 C++ 代码的命令。
FC
用于编译 Fortran 代码的命令。
PKG_CONFIG
pkg-config 工具的路径。
特定架构的环境变量:
GOARM
用于 GOARCH=arm,表示编译的 ARM 架构。
有效的值为 5、6、7。
GO386
用于 GOARCH=386,指定如何实现浮点指令。
有效的值为 sse2(默认)和 softfloat。
GOAMD64
用于 GOARCH=amd64,表示编译的微架构级别。
有效的值为 v1(默认)、v2、v3、v4。
参见 https://golang.org/wiki/MinimumRequirements#amd64。
GOMIPS
用于 GOARCH=mips{,le},表示是否使用浮点指令。
有效的值为 hardfloat(默认)和 softfloat。
GOMIPS64
用于 GOARCH=mips64{,le},表示是否使用浮点指令。
有效的值为 hardfloat(默认)和 softfloat。
GOPPC64
用于 GOARCH=ppc64{,le},表示目标 ISA(指令集架构)。
有效的值为 power8(默认)、power9 和 power10。
GOWASM
用于 GOARCH=wasm,以逗号分隔的实验性 WebAssembly 功能列表。
有效的值为 satconv 和 signext。
用于代码覆盖的环境变量:
GOCOVERDIR
"go build -cover" 二进制文件生成的代码覆盖数据文件将写入其中的目录。
需要启用 GOEXPERIMENT=coverageredesign。
特殊用途的环境变量:
GCCGOTOOLDIR
如果设置了,gccgo 工具的所在位置,例如 cgo。
默认值基于 gccgo 的配置。
GOEXPERIMENT
启用或禁用的工具链实验的逗号分隔列表。
可用实验的列表可能随时更改。
有关目前有效值,请参见 src/internal/goexperiment/flags.go。
警告:此变量仅为开发和测试 Go 工具链本身提供。
超出此目的的使用不受支持。
GOROOT_FINAL
安装 Go 树的根目录,当它安装在与构建位置不同的位置时。
堆栈跟踪中的文件名将从 GOROOT 重写为 GOROOT_FINAL。
GO_EXTLINK_ENABLED
使用 -linkmode=auto 与使用 cgo 的代码时,
链接器是否应使用外部链接模式。
将其设置为 0 以禁用外部链接模式,设置为 1 以启用。
GIT_ALLOW_PROTOCOL
Git 定义的允许使用 git fetch/clone 的方案的冒号分隔列表。
如果设置,未明确提及的任何方案都将被 'go get' 视为不安全。
因为该变量由 Git 定义,所以不能使用 'go env -w' 设置默认值。
从 ‘go env’ 中获取的其他信息,但不是从环境中读取的:
GOEXE
可执行文件名后缀(Windows 上为".exe",其他系统上为空字符串)。
GOGCCFLAGS
CC 命令提供的参数的以空格分隔的列表。
GOHOSTARCH
Go 工具链二进制文件的架构(GOARCH)。
GOHOSTOS
Go 工具链二进制文件的操作系统(GOOS)。
GOMOD
主模块的 go.mod 的绝对路径。
如果启用了模块感知模式,
但没有 go.mod,则 GOMOD 将是 os.DevNull
(在类 Unix 系统上为"/dev/null",在 Windows 上为"NUL")。
如果禁用了模块感知模式,则 GOMOD 将为空字符串。
GOTOOLDIR
Go 工具(compile、cover、doc 等)所在的目录。
GOVERSION
安装的 Go 树的版本,由 runtime.Version 报告。
文件类型
go 命令检查每个目录中一组受限制的文件的内容。 它根据文件名的扩展名来确定要检查哪些文件。 这些扩展名是:
.go
Go源文件。
.c, .h
C源文件。
如果包使用cgo或SWIG,
则这些文件将使用本机编译器(通常是gcc)编译;
否则它们会导致错误。
.cc, .cpp, .cxx, .hh, .hpp, .hxx
C++源文件。仅在使用cgo或SWIG时有用,并且始终使用本机编译器编译。
.m
Objective-C源文件。仅在使用cgo时有用,并始终使用本机编译器编译。
.s, .S, .sx
汇编器源文件。
如果包使用cgo或SWIG,则这些文件将使用本机汇编器(通常是gcc)汇编;
否则它们将使用Go汇编器汇编。
.swig, .swigcxx
SWIG定义文件。
.syso
系统对象文件。
除了.syso之外,每个这些类型的文件都可以包含构建约束条件,但是go命令会在第一个不是空白行或//-样式行注释的条目处停止扫描构建约束条件。有关更多详细信息,请参阅go/build包文档。
go.mod文件
模块版本由源文件树定义,在其根目录中有一个go.mod文件。运行go命令时,它会在当前目录中查找,然后在父目录中查找,以找到标记当前模块根的go.mod文件。
go.mod文件格式在https://golang.org/ref/mod#go-mod-file中详细描述。
要创建新的go.mod文件,请使用’go mod init’。有关详细信息,请参见’go help mod init’或https://golang.org/ref/mod#go-mod-init。
要添加缺少的模块要求或删除不需要的要求,请使用’go mod tidy’。有关详细信息,请参见’go help mod tidy’或https://golang.org/ref/mod#go-mod-tidy。
要添加、升级、降级或删除特定模块要求,请使用’go get’。有关详细信息,请参见’go help module-get’或https://golang.org/ref/mod#go-get。
要进行其他更改或将go.mod解析为JSON供其他工具使用,请使用’go mod edit’。请参阅’go help mod edit’或https://golang.org/ref/mod#go-mod-edit。
GOPATH环境变量
Go路径用于解析导入语句。它由go/build包实现并记录。
GOPATH环境变量列出了查找Go代码的位置。在Unix上,该值是以冒号分隔的字符串。在Windows上,该值是以分号分隔的字符串。在Plan 9上,该值是一个列表。
如果环境变量未设置,GOPATH默认为用户主目录中名为"go"的子目录(在Unix上为$HOME/go,在Windows上为%USERPROFILE%\go),除非该目录包含Go发行版。运行"go env GOPATH"可以查看当前GOPATH。
请参见https://golang.org/wiki/SettingGOPATH来设置自定义GOPATH。
GOPATH中列出的每个目录都必须具有预定的结构:
-
src目录包含源代码。src下面的路径确定导入路径或可执行文件名。
-
pkg目录保存已安装的包对象。与Go树中一样,每个目标操作系统和架构对都有自己的pkg子目录(pkg/GOOS_GOARCH)。
如果DIR是在GOPATH中列出的目录,则具有DIR/src/foo/bar中的源代码的包可以作为"foo/bar"导入,并将其编译形式安装到"DIR/pkg/GOOS_GOARCH/foo/bar.a"中。
- bin目录保存已编译的命令。每个命令以其源目录命名,但只使用最后一个元素,而不是整个路径。也就是说,具有DIR/src/foo/quux源代码的命令将安装到DIR/bin/quux,而不是DIR/bin/foo/quux。前缀"foo/“被删除,以便您可以将DIR/bin添加到PATH中以获得已安装命令。如果设置了GOBIN环境变量,则命令将安装到其命名的目录,而不是DIR/bin。GOBIN必须是绝对路径。
这是一个示例目录布局:
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
Go会在GOPATH列表中的每个目录中查找源代码,但新的包总是被下载到列表中第一个目录。
参见 https://golang.org/doc/code.html 获取示例。
GOPATH 和 Modules
使用 modules 时,GOPATH 不再用于解析导入。但是,它仍然用于存储已下载的源代码(在 GOPATH/pkg/mod 中)和编译的命令(在 GOPATH/bin 中)。
内部目录
位于名为"internal"的目录中或以下的代码只能被根目录为"internal"的目录树中的代码导入。下面是上述目录布局的扩展版本:
/home/user/go/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
internal/
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
在 z.go 中导入为"foo/internal/baz”,但是该导入语句只能出现在以 foo 为根的子树中的源文件中。foo/f.go、foo/bar/x.go 和 foo/quux/y.go 中的源文件都可以导入"foo/internal/baz",但是 crash/bang/b.go 中的源文件不能。
有关详细信息,请参见 https://golang.org/s/go14internal。
vendor目录
Go 1.6 包括使用本地副本来满足这些依赖项的导入的支持,通常称为供应商。
位于名为"vendor"的目录以下的代码只能由根目录为"vendor"的目录树中的代码导入,并且仅使用省略前缀直到包含 vendor 元素的路径。
下面是前一节的示例,但将"internal"目录重命名为"vendor"并添加了一个新的 foo/vendor/crash/bang 目录:
/home/user/go/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
vendor/
crash/
bang/ (go code in package bang)
b.go
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
同样的可见性规则适用于 internal,但是 z.go 中的代码导入时使用 “baz”,而不是 “foo/vendor/baz”。
位于更深层次的 vendor 目录中的代码会遮蔽较高层次的目录中的代码。在以 foo 为根的子树中,对 “crash/bang” 的导入会解析为 “foo/vendor/crash/bang”,而不是顶层的 “crash/bang”。
位于 vendor 目录中的代码不受导入路径检查的限制(参见 ‘go help importpath’)。
当 ‘go get’ 检出或更新 git 子模块时,它现在也会更新子模块。
vendor 目录不影响由 ‘go get’ 第一次检出的新代码库的位置:它们总是被放置在主 GOPATH 中,而不是在 vendor 子目录中。
详见 https://golang.org/s/go15vendor。
遗留 GOPATH go get
‘go get’ 命令的行为取决于 go 命令是在模块感知模式还是遗留 GOPATH 模式下运行。即使在模块感知模式下,也可以通过 ‘go help gopath-get’ 访问此帮助文本,它描述了 ‘go get’ 在遗留 GOPATH 模式下的操作。
用法:
go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]
get 下载指定导入路径的包及其依赖项。它然后安装指定的包,就像 ‘go install’ 一样。
-d 标志指示 get 在下载包后停止,即指示 get 不安装包。
-f 标志只在设置了 -u 标志时有效,强制 get -u 不验证每个包是否已从其导入路径所暗示的源代码库检出。如果源代码是原始代码的本地分支,则此功能可能很有用。
-fix 标志指示 get 在解析依赖项或构建代码之前对下载的包运行 fix 工具。
-t 标志指示 get 也下载构建指定包所需的测试包。
-u 标志指示 get 使用网络更新指定的包及其依赖项。默认情况下,get 使用网络检出缺少的包,但不使用网络查找现有包的更新。
-v 标志启用详细进度和调试输出。
get 命令还接受构建标志以控制安装。请参阅 ‘go help build’。
在检出新包时,get 会创建目标目录 GOPATH/src/
在检出或更新包时,get 会查找与本地安装的 Go 版本匹配的分支或标记。最重要的规则是,如果本地安装正在运行版本 “go1”,则 get 会搜索名为 “go1” 的分支或标记。如果不存在此类版本,则检索包的默认分支。
当 go get 检出或更新 Git 存储库时,它也会更新由存储库引用的任何 git 子模块。
get 永远不会检出或更新存储在 vendor 目录中的代码。
有关指定包的更多信息,请参阅 ‘go help packages’。
有关 ‘go get’ 如何查找要下载的源代码的更多信息,请参阅 ‘go help importpath’。
本文描述了使用 GOPATH 管理源代码和依赖项时的 get 行为。如果 go 命令是在模块感知模式下运行,则 get 的标志和效果的详细信息会发生更改,‘go help get’ 也会发生更改。请参阅 ‘go help modules’ 和 ‘go help module-get’。
另请参阅:go build、go install、go clean。
模块代理协议
Go 模块代理是任何可以响应特定格式 URL 的 GET 请求的 Web 服务器。请求没有查询参数,因此即使是从固定文件系统(包括 file://URL)服务的站点也可以是模块代理。
有关 GOPROXY 协议的详细信息,请参阅 https://golang.org/ref/mod#goproxy-protocol。
导入路径语法
导入路径(请参阅 ‘go help packages’)表示存储在本地文件系统中的包。一般来说,导入路径表示标准包(如 “unicode/utf8”)或在工作区之一找到的包(有关详细信息,请参阅:‘go help gopath’)。
相对导入路径
以 ./ 或 ../ 开头的导入路径称为相对路径。工具链支持相对导入路径作为两种快捷方式。
首先,相对路径可以作为命令行上的快捷方式。如果您在包含代码作为 “unicode” 导入的目录中工作,并想要运行 “unicode/utf8” 的测试,则可以键入 “go test ./utf8” 而不需要指定完整路径。同样,在反向情况下,“go test ..“将从 “unicode/utf8” 目录测试 “unicode”。相对模式也被允许,例如 “go test ./…” 可以测试所有子目录。有关模式语法的详细信息,请参见 ‘go help packages’。
其次,如果您在不在工作空间中编译 Go 程序,那么您可以在该程序的导入语句中使用相对路径,以引用附近的代码,也不在工作空间中。这使得在通常的工作空间之外实验小型多包程序非常容易,但这些程序无法使用 “go install” 进行安装(没有工作空间来安装它们),因此每次构建时都会重新构建。为避免歧义,Go 程序不能在工作空间内使用相对导入路径。
远程导入路径
某些导入路径也描述了如何使用版本控制系统获取软件包的源代码。
一些常见的代码托管站点有特殊的语法:
Bitbucket (Git, Mercurial)
import "bitbucket.org/user/project"
import "bitbucket.org/user/project/sub/directory"
GitHub (Git)
import "github.com/user/project"
import "github.com/user/project/sub/directory"
Launchpad (Bazaar)
import "launchpad.net/project"
import "launchpad.net/project/series"
import "launchpad.net/project/series/sub/directory"
import "launchpad.net/~user/project/branch"
import "launchpad.net/~user/project/branch/sub/directory"
IBM DevOps Services (Git)
import "hub.jazz.net/git/user/project"
import "hub.jazz.net/git/user/project/sub/directory"
对于在其他服务器上托管的代码,导入路径可以使用版本控制类型进行限定,或者 go 工具可以通过 https/http 动态获取导入路径,并从 HTML 的 标记中发现代码所在的位置。
要声明代码位置,形式为
repository.vcs/path
的导入路径指定了给定的仓库,带或不带 .vcs 后缀,使用命名的版本控制系统,然后是该仓库内的路径。支持的版本控制系统是:
Bazaar .bzr
Fossil .fossil
Git .git
Mercurial .hg
Subversion .svn
例如,
import "example.org/user/foo.hg"
表示在 example.org/user/foo 或 foo.hg 上的 Mercurial 存储库的根目录,而
import "example.org/repo.git/foo/bar"
表示 example.org/repo 或 repo.git 上的 Git 存储库的 foo/bar 目录。
当版本控制系统支持多个协议时,每个协议都会依次尝试下载。例如,Git 下载尝试 https://,然后是 git+ssh://。
默认情况下,下载仅限于已知的安全协议(例如 https、ssh)。要覆盖此设置以进行 Git 下载,可以设置 GIT_ALLOW_PROTOCOL 环境变量(有关更多详细信息,请参见 ‘go help environment’)。
如果导入路径不是已知的代码托管站点,也缺乏版本控制限定符,则 go 工具尝试通过 https/http 获取导入,并在文档的 HTML <head> 中查找 <meta> 标签。
meta 标签的形式为:
<meta name="go-import" content="import-prefix vcs repo-root">
import-prefix 是与存储库根目录对应的导入路径。它必须是被 “go get” 获取的包的前缀或精确匹配。如果它不是精确匹配,则会在该前缀处进行另一个 http 请求以验证 标签的匹配。
meta 标签应尽可能早地出现在文件中。特别是,它应该出现在任何原始 JavaScript 或 CSS 之前,以避免混淆 go 命令的受限解析器。
vcs 是 “bzr”、“fossil”、“git”、“hg”、“svn” 之一。
repo-root 是包含方案但不包含 .vcs 限定符的版本控制系统的根。
例如,
import "example.org/pkg/foo"
将导致以下请求:
https://example.org/pkg/foo?go-get=1(首选)
http://example.org/pkg/foo?go-get=1(回退,仅在正确设置了 GOINSECURE 的情况下)
如果该页面包含以下 meta 标签
<meta name="go-import" content="example.org git https://code.org/r/p/exproj">
go 工具将验证 https://example.org/?go-get=1 是否包含相同的 meta 标签,然后将 git 克隆 https://code.org/r/p/exproj 到 GOPATH/src/example.org。
在使用 GOPATH 时,下载的包会写入 GOPATH 环境变量中列出的第一个目录。(请参见 ‘go help gopath-get’ 和 ‘go help gopath’。)
在使用模块时,下载的包存储在模块缓存中。请参阅 Go模块参考中的模块缓存命令。
使用模块时,还有一种go-import meta标签的变体会被识别,并且优先于列出版本控制系统的标签。这个变体在content值中使用"mod"作为vcs,例如:
<meta name="go-import" content="example.org mod https://code.org/moduleproxy">
这个标签意味着要从可用于URL https://code.org/moduleproxy 的模块代理中获取以example.org开头的模块。有关代理协议的详细信息,请参见Go模块参考中的模块代理。
导入路径检查
当上述自定义导入路径功能重定向到已知的代码托管站点时,每个结果包都有两个可能的导入路径,一个是使用自定义域名,另一个是使用已知的托管站点。
如果一个包语句紧接着(在下一个换行符之前)有一个这两种形式之一的注释,那么它被称为"导入注释”:
package math // import "path"
package math /* import "path" */
go命令将拒绝安装带有导入注释的包,除非它被引用了该导入路径。通过这种方式,导入注释让包的作者确保使用自定义导入路径,而不是底层的代码托管站点的直接路径。
在vendor树中发现的代码不会进行导入路径检查。这使得可以将代码复制到vendor树中的其他位置,而不需要更新导入注释。
当使用模块时,导入路径检查也被禁用了。导入路径注释被go.mod文件中的模块声明所取代。
有关详细信息,请参见https://golang.org/s/go14customimport。
模块、模块版本等
模块是Go管理依赖项的方式。
一个模块是一组一起发布、版本化和分发的包。模块可以直接从版本控制存储库或模块代理服务器下载。
有关模块教程系列,请参见https://golang.org/doc/tutorial/create-module。
有关模块的详细参考,请参见Go模块参考。
默认情况下,go命令可以从https://proxy.golang.org下载模块。它可以使用https://sum.golang.org上的checksum数据库对模块进行身份验证。这两个服务都由Google的Go团队运营。这些服务的隐私政策可在https://proxy.golang.org/privacy和https://sum.golang.org/privacy上获得。
可以使用GOPROXY、GOSUMDB、GOPRIVATE和其他环境变量来配置go命令的下载行为。有关更多信息,请参见"go help environment"和Go模块参考中的私有模块中的隐私。
使用 go.sum 进行模块认证
当 go 命令将模块 zip 文件或 go.mod 文件下载到模块缓存中时,它会计算一个密码哈希值并将其与已知值进行比较,以验证该文件自从第一次下载以来没有发生更改。已知哈希值存储在模块根目录中名为 go.sum 的文件中。哈希值也可以根据 GOSUMDB、GOPRIVATE 和 GONOSUMDB 的值从校验和数据库中下载。
For details, see Go模块参考中的验证模块.
软件包列表和模式
许多命令都适用于一组软件包:
go action [packages]
通常,[packages] 是一组导入路径。
一个根路径或以 . 或 .. 元素开头的导入路径被解释为文件系统路径,并表示该目录中的软件包。
否则,导入路径 P 表示在 GOPATH 环境变量列出的某个 DIR/src/P 目录中找到的软件包(有关详细信息,请参阅 ‘go help gopath’)。
如果没有给出导入路径,则该操作适用于当前目录中的软件包。
有四个保留名称用于不应与 go 工具一起构建的软件包:
- “main"表示独立可执行文件中的顶级包。
- “all"展开为在所有 GOPATH 树中找到的所有软件包。例如,‘go list all’ 列出了本地系统上的所有软件包。当使用模块时,“all"会展开为主模块中的所有软件包及其依赖项,包括任何这些依赖项的测试所需的依赖项。
- “std"类似于"all”,但仅展开到标准 Go 库中的软件包。
- “cmd"展开为 Go 存储库的命令及其内部库。
以"cmd/“开头的导入路径仅匹配 Go 存储库中的源代码。
如果导入路径包含一个或多个”...“通配符,则导入路径是一个模式,每个通配符可以匹配任何字符串,包括空字符串和包含斜杠的字符串。这种模式将展开为 GOPATH 树中找到的所有软件包目录,其名称与模式匹配。
为了方便常见模式的匹配,有两个特殊情况。第一种情况是在模式末尾添加 /... 可以匹配空字符串,例如 net/... 同时匹配 net 和其子目录下的包,如 net/http。第二种情况是任何包含通配符的斜杠分隔模式元素都不会匹配 vendored 包路径中的 “vendor” 元素,这样 ./... 就不会匹配 ./vendor 或 ./mycode/vendor 子目录下的包,但是 ./vendor/... 和 ./mycode/vendor/... 会。然而,一个包含代码的名为 vendor 的目录不是一个 vendored 包:cmd/vendor 将是一个名为 vendor 的命令,模式 cmd/... 会匹配它。有关 vendoring 的更多信息,请参见 golang.org/s/go15vendor。
导入路径也可以命名从远程仓库下载的包。有关详情,请运行"go help importpath”。
程序中的每个包都必须具有唯一的导入路径。按照惯例,这是通过将每个路径以属于你自己的唯一前缀开头来安排的。例如,在 Google 内部使用的路径都以 ‘google’ 开头,表示远程仓库的路径以代码的路径为开头,例如 ‘github.com/user/repo’。
程序中的包名不需要唯一,但有两个保留的包名具有特殊含义。名称 main 表示命令,而不是库。命令被构建成二进制文件,不能被导入。名称 documentation 表示目录中非 Go 程序的文档。包文档中的文件将被 go 命令忽略。
作为特殊情况,如果包列表是来自单个目录的 .go 文件列表,则该命令将应用于一个合成包,该包由恰好这些文件组成,忽略这些文件中的任何构建约束,并忽略目录中的任何其他文件。
以 “.” 或 “_” 开头的目录和文件名将被 go 工具忽略,同样以 “testdata” 命名的目录也会被忽略。
用于下载非公共代码的配置
go 命令默认从公共 Go 模块镜像 proxy.golang.org 下载模块。无论源代码如何,它还默认针对公共 Go 校验和数据库 sum.golang.org 验证下载的模块。这些默认值适用于公开的源代码。
GOPRIVATE 环境变量控制了哪些模块被 go 命令视为私有模块(不公开可用),因此不应使用代理或校验和数据库。该变量是一个以逗号分隔的模块路径前缀的通配符模式列表(符合 Go 的 path.Match 语法)。例如,
GOPRIVATE=*.corp.example.com,rsc.io/private
会使 go 命令将任何具有与其中任意一种模式匹配的路径前缀的模块视为私有模块,包括 git.corp.example.com/xyzzy、rsc.io/private 和 rsc.io/private/quux 等。
为了对模块下载和校验有更精细的控制,GONOPROXY 和 GONOSUMDB 环境变量接受相同类型的通配符模式列表,并分别覆盖 GOPRIVATE,用于确定是否使用代理和校验和数据库。
例如,如果公司运行一个用于服务私有模块的模块代理,则用户可以使用以下方式配置 go:
GOPRIVATE=*.corp.example.com
GOPROXY=proxy.example.com
GONOPROXY=none
GOPRIVATE 变量还用于定义 GOVCS 变量的 “public” 和 “private” 模式;请参阅 ‘go help vcs’。对于这种用法,GOPRIVATE 即使在 GOPATH 模式下也适用。在这种情况下,它匹配导入路径而不是模块路径。
可以使用 ‘go env -w’ 命令(参见 ‘go help env’)为将来的 go 命令调用设置这些变量。
有关更多详细信息,请参阅Go模块参考中的私有模块。
测试标志
‘go test’ 命令接受适用于 ‘go test’ 自身和适用于生成的测试二进制文件的标志。
其中一些标志控制分析,并编写适用于 “go tool pprof” 的执行分析文件;运行 “go tool pprof -h” 以获取更多信息。pprof 的 --alloc_space、--alloc_objects 和 --show_bytes 选项控制信息的显示方式。
以下标志由 ‘go test’ 命令识别并控制任何测试的执行:
-bench regexp
仅运行与正则表达式匹配的基准测试。
默认情况下,不运行基准测试。
要运行所有基准测试,请使用"-bench。"或"-bench =。"。
正则表达式由未加括号的斜杠(/)字符拆分为一系列正则表达式,
并且基准标识符的每个部分必须与序列中的相应元素匹配(如果有)。
匹配项的可能父项以b.N = 1运行,以确定子基准测试。
例如,给定-bench = X / Y,将使用b.N = 1运行与X匹配的顶级基准测试,
以查找任何与Y匹配的子基准测试,然后以完整形式运行它们。
-benchtime t
运行足够的迭代来花费t,t以time.Duration形式指定
(例如,-benchtime 1h30s)。默认为1秒(1s)。
特殊语法Nx表示运行基准测试N次(例如,-benchtime 100x)。
-count n
对每个测试、基准测试和模糊种子运行n次(默认为1次)。
如果设置了-cpu,则对每个GOMAXPROCS值运行n次。
示例总是运行一次。-count不适用于由-fuzz匹配的模糊测试。
-cover
启用覆盖分析。
请注意,由于覆盖工作是通过编译前对源代码进行注释来完成的,
因此启用覆盖并编译或测试失败可能会报告与原始源不对应的行号。
-covermode set,count,atomic
为正在测试的包设置覆盖分析模式。默认为"set",
除非启用了-race,此时为"atomic"。
值:
set:bool:是否运行此语句?
count:int:此语句运行多少次?
atomic:int:count,但在多线程测试中正确;显著更昂贵。
设置-cover。
-coverpkg pattern1,pattern2,pattern3
在每个测试中将覆盖分析应用于与模式匹配的包。
默认情况下,每个测试仅分析正在测试的包。
有关包模式的描述,请参见"go help packages"。
设置-cover。
-cpu 1,2,4
指定测试、基准测试或模糊测试应执行的GOMAXPROCS值列表。
默认值为GOMAXPROCS的当前值。-cpu不适用于由-fuzz匹配的模糊测试。
-failfast
第一个测试失败后不要启动新测试。
-fuzz regexp
运行匹配正则表达式的模糊测试。
指定时,命令行参数必须恰好匹配主模块中的一个包,
并且 regexp 必须恰好匹配该包中的一个模糊测试。
模糊测试将在测试、基准测试、其他模糊测试的种子库和示例完成后进行。
有关详细信息,请参见测试包文档中的"模糊测试"部分。
-fuzztime t
运行足够的迭代次数来执行指定的时间 t 的模糊测试目标
(例如,-fuzztime 1h30s)。
默认情况下,将永久运行。
特殊语法 Nx 表示运行模糊测试目标 N 次(例如,-fuzztime 1000x)。
-fuzzminimizetime t
在每个最小化尝试期间运行足够的迭代次数以执行指定的时间 t
(例如,-fuzzminimizetime 30s)。
默认情况下为 60 秒。
特殊语法 Nx 表示运行模糊测试目标 N 次
(例如,-fuzzminimizetime 100x)。
-json
以 JSON 形式记录详细输出和测试结果。
这以机器可读的格式呈现与 -v 标志相同的信息。
-list regexp
列出与正则表达式匹配的测试、基准测试、模糊测试或示例。
不会运行任何测试、基准测试、模糊测试或示例。
仅列出顶级测试。不会显示子测试或子基准测试。
-parallel n
允许并行执行调用 t.Parallel 的测试函数,
以及运行种子库时调用 t.Parallel 的模糊测试。
此标志的值是同时运行的最大测试数。
在进行模糊测试时,此标志的值是可以调用模糊函数的子进程的最大数量,
无论是否调用了 T.Parallel。
默认情况下,-parallel 设置为 GOMAXPROCS 的值。
将 -parallel 设置为比 GOMAXPROCS 更高的值可能会导致因 CPU 争用
而降低性能,特别是在进行模糊测试时。
请注意,-parallel 仅适用于单个测试二进制文件。
'go test' 命令也可以并行运行不同包的测试,
根据 -p 标志的设置(请参阅 'go help build')。
-run regexp
仅运行与正则表达式匹配的测试、示例和模糊测试。
对于测试来说,
正则表达式被不带方括号的斜杠字符(/)分隔成一系列正则表达式,
每个测试标识符的部分必须与序列中的相应元素匹配(如果有的话)。
请注意,可能的匹配项的父级也会运行,
因此-run=X/Y会匹配并运行和报告与X匹配的所有测试,
即使没有子测试与Y匹配,也必须运行它们来查找这些子测试。
另请参见-skip。
-short
告诉长时间运行的测试缩短运行时间。
默认情况下关闭,但在all.bash期间设置,
以便安装Go树可以运行一次健全性检查,但不必花费时间运行详尽的测试。
-shuffle off,on,N
随机执行测试和基准的顺序。默认情况下关闭。
如果将-shuffle设置为on,则它将使用系统时钟作为种子生成随机数。
如果将-shuffle设置为整数N,则N将用作种子值。
在这两种情况下,种子将报告以实现可重现性。
-skip regexp
仅运行与正则表达式不匹配的测试、示例、模糊测试和基准。
就像对于-run和-bench一样,对于测试和基准,
正则表达式被不带方括号的斜杠(/)字符分隔成一系列正则表达式,
每个测试标识符的部分必须与序列中的相应元素匹配(如果有的话)。
-timeout d
如果测试二进制文件运行时间超过d,
将会发生panic。如果d为0,则禁用超时。默认为10分钟(10m)。
-v
输出详细信息:记录所有运行的测试。即使测试成功,
也打印来自Log和Logf调用的所有文本。
-vet list
配置"go test"期间"go vet"的调用,
使用逗号分隔的vet检查列表。
如果列表为空,
"go test"将使用一个由认为值得处理的检查组成的精选列表运行"go vet"。
如果列表为"off","go test"根本不运行"go vet"。
以下标记也可以被’go test’识别并用于在执行过程中对测试进行分析:
-benchmem
打印基准测试的内存分配统计信息。
-blockprofile block.out
当所有测试完成时,将 goroutine 阻塞分析文件写入指定文件。
写入测试二进制文件与 '-c' 相同。
-blockprofilerate n
通过调用 runtime.SetBlockProfileRate(n)
控制 goroutine 阻塞分析中的详细信息。
请参阅 'go doc runtime.SetBlockProfileRate'。
分析器的目标是平均每 n 纳秒程序阻塞时采样一个阻塞事件。
默认情况下,如果在未使用此标志的情况下设置了-test.blockprofile,
则记录所有阻塞事件,相当于-test.blockprofilerate = 1。
-coverprofile cover.out
在所有测试通过后将覆盖率分析结果写入文件。
设置 -cover。
-cpuprofile cpu.out
在退出之前将 CPU 分析结果写入指定的文件中。
写入测试二进制文件,就像-c一样。
-memprofile mem.out
在所有测试通过后,将分配分析结果写入指定的文件中。
写入测试二进制文件,就像-c一样。
-memprofilerate n
通过设置 runtime.MemProfileRate
来启用更精确(也更昂贵)的内存分配分析。
请参阅"go doc runtime.MemProfileRate"。
要分析所有内存分配,请使用-test.memprofilerate = 1。
-mutexprofile mutex.out
当所有测试都完成后,将一个互斥锁争用分析文件写入指定的文件中。
写入测试二进制文件,就像-c一样。
-mutexprofilefraction n
对持有有争议的互斥锁的 goroutine 进行1:n的堆栈跟踪采样。
-outputdir directory
将性能分析的输出文件放置在指定的目录中,
默认情况下是"go test"正在运行的目录。
-trace trace.out
在退出之前将执行跟踪结果写入指定的文件中。
每个标志也可以使用可选的"test.“前缀,例如 -test.v。但是,当直接调用生成的测试二进制文件(即"go test -c"的结果)时,前缀是必需的。
“go test"命令会在可选的包列表之前和之后重写或删除已识别的标志,然后调用测试二进制文件。
例如,命令
go test -v -myflag testdata -cpuprofile=prof.out -x
将编译测试二进制文件,然后将其作为以下方式运行
pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
(-x 标志被删除,因为它仅适用于 go 命令的执行,而不适用于测试本身。)
生成剖析的测试标志(除了覆盖率之外)也会将测试二进制文件留在 pkg.test 中,以便在分析剖析时使用。
当"go test"运行测试二进制文件时,它是从相应的包的源代码目录中运行的。根据测试的不同,调用生成的测试二进制文件时可能需要执行相同的操作。因为该目录可能位于模块缓存中,而模块缓存可能是只读的并且由校验和进行验证,所以测试不能将其或模块中的任何其他目录写入,除非用户明确请求(例如使用 -fuzz 标志,将失败写入 testdata/fuzz)。
如果存在命令行包列表,则必须在任何未知于 go test 命令的标志之前出现。继续上面的例子,包列表必须出现在 -myflag 之前,但可以出现在 -v 的任何一侧。
当"go test"以包列表模式运行时,“go test"会缓存成功的包测试结果,以避免不必要的重复运行测试。要禁用测试缓存,请使用任何不可缓存的标志或参数。显式禁用测试缓存的惯用方法是使用 -count=1。
要使测试二进制文件的参数不被解释为已知标志或包名,请使用 -args(请参见"go help test”),该标志会将命令行的剩余部分传递给测试二进制文件,未经解释和未被改变。
例如,命令
go test -v -args -x -v
将编译测试二进制文件,然后将其作为以下方式运行
pkg.test -test.v -x -v
同样,
go test -args math
将编译测试二进制文件,然后将其作为以下方式运行
pkg.test math
在第一个例子中,-x和第二个-v参数被原封不动地传递给测试二进制文件,不会对go命令本身产生影响。在第二个例子中,参数math被传递给测试二进制文件,而不是被解释为包列表。
测试函数
‘go test’ 命令期望在对应被测试包的 “*_test.go” 文件中找到测试、基准测试和示例函数。
测试函数以 TestXxx 命名(其中 Xxx 不以小写字母开头),应该有如下签名:
func TestXxx(t *testing.T) { ... }
基准测试函数以 BenchmarkXxx 命名,应该有如下签名:
func BenchmarkXxx(b *testing.B) { ... }
模糊测试以 FuzzXxx 命名,应该有如下签名:
func FuzzXxx(f *testing.F) { ... }
示例函数与测试函数类似,但是输出到 os.Stdout 而不是使用 *testing.T 来报告成功或失败。如果函数的最后一个注释以 “Output:” 开头,则输出与注释进行完全匹配(参见下面的示例)。如果最后一个注释以 “Unordered output:” 开头,则输出与注释进行匹配,但是忽略行的顺序。没有此类注释的示例会被编译但不会被执行。在 “Output:” 后没有文本的示例会被编译、执行,并期望不产生输出。
Godoc 显示 ExampleXxx 的正文,以演示函数、常量或变量 Xxx 的使用。具有接收者类型 T 或 *T 的方法 M 的示例命名为 ExampleT_M。对于给定函数、常量或变量,可以有多个示例,它们通过一个尾部 _xxx 区分开,其中 xxx 是一个不以大写字母开头的后缀。
下面是一个示例:
func ExamplePrintln() {
Println("The output of\nthis example.")
// Output: The output of
// this example.
}
下面是另一个示例,其中输出的顺序被忽略:
func ExamplePerm() {
for _, value := range Perm(4) {
fmt.Println(value)
}
// Unordered output: 4
// 2
// 1
// 3
// 0
}
当测试文件包含一个单独的示例函数、至少一个其他函数、类型、变量或常量声明以及没有测试、基准测试或模糊测试时,整个测试文件将被作为示例呈现。
有关更多信息,请参阅 testing 包的文档。
用 GOVCS 控制版本控制
‘go get’ 命令可以运行版本控制命令(如 git)来下载导入的代码。这个功能对于 Go 分散式包生态系统至关重要,其中的代码可以从任何服务器导入,但如果恶意服务器找到了一种方法来让调用的版本控制命令运行未预期的代码,这也是一个潜在的安全问题。
为了平衡功能和安全问题,‘go get’ 命令默认只使用 git 和 hg 从公共服务器下载代码。但它将使用任何已知的版本控制系统(bzr、fossil、git、hg、svn)从私有服务器下载代码,这些服务器定义为托管匹配 GOPRIVATE 变量(请参见 ‘go help private’)的包。允许 Git 和 Mercurial 的原理在于这两个系统在作为不受信任服务器的客户端运行时已经得到了最多的问题关注。相比之下,Bazaar、Fossil 和 Subversion 主要用于受信任的身份验证环境中,并且没有像攻击面一样受到充分的审查。
版本控制命令限制仅适用于使用直接版本控制访问下载代码时。当从代理服务器下载模块时,‘go get’ 使用代理协议,该协议始终被允许。默认情况下,‘go get’ 命令使用 Go 模块镜像(proxy.golang.org)获取公共包,仅在模块镜像拒绝为公共包提供服务(通常是因为法律原因)时,才回退到版本控制以获取私有包。因此,客户端仍然可以访问由 Bazaar、Fossil 或 Subversion 存储库提供的公共代码,默认情况下,因为这些下载使用 Go 模块镜像,该镜像承担运行版本控制命令的安全风险,使用自定义沙箱。
GOVCS 变量可用于更改特定包(由模块或导入路径标识)的允许版本控制系统。GOVCS 变量在模块感知模式和 GOPATH 模式下构建包时都适用。当使用模块时,模式与模块路径匹配。使用 GOPATH 时,模式与对应于版本控制存储库根的导入路径匹配。
GOVCS 的一般形式为 pattern:vcslist 规则,由逗号分隔的一组规则构成。pattern 是必须匹配模块或导入路径的一个或多个前导元素的 glob 模式。vcslist 是允许的版本控制命令的管道分隔列表,或者是 “all” 表示允许使用任何已知命令,或者是 “off” 表示禁止使用所有命令。请注意,如果一个模块匹配一个 vcslist 为 “off” 的模式,则仍可以下载,如果源服务器使用 “mod” 方案,则指示 go 命令使用 GOPROXY 协议下载模块。列表中最早匹配的模式优先应用,即使后面的模式也匹配。
例如,请考虑:
GOVCS=github.com:git,evil.com:off,*:git|hg
使用此设置,具有以 github.com/ 开头的模块或导入路径的代码只能使用 git。evil.com 上的路径不能使用任何版本控制命令,而其他所有路径(* 匹配所有)只能使用 git 或 hg。
特殊模式 “public” 和 “private” 匹配公共和私有模块或导入路径。如果路径与 GOPRIVATE 变量匹配,则为私有路径;否则为公共路径。
如果 GOVCS 变量中没有规则与特定模块或导入路径匹配,则 ‘go get’ 命令应用其默认规则,该规则现在可以用 GOVCS 表示为 ‘public:git|hg,private:all’。
要允许任何包使用任何版本控制系统,可以使用:
GOVCS=*:all
要禁用所有版本控制的使用,请使用:
GOVCS=*:off
“go env -w” 命令(请参阅 “go help env”)可用于设置 GOVCS 变量以供将来的 go 命令调用。
1.3.14 - go 命令首页表格
Command Documentation - 命令文档
有一套程序用于构建和处理 Go 源代码。这套程序通常由go程序调用,而不是直接运行。
运行这些程序最常见的方式是作为 go 程序的一个子命令,例如 go fmt。以这种方式运行,该命令对完整的 Go 源代码包进行操作,go 使用适合于包级别处理的参数调用底层二进制文件。
这些程序也可以作为独立的二进制文件运行,带有未做修改的参数,使用go tool子命令,如go tool cgo。对于大多数命令来说,主要用于调试。有些命令,如pprof,只能通过go tool子命令来访问。
最后,fmt和godoc命令被安装成常规的二进制文件,称为gofmt和godoc,因为它们经常被引用。
点击链接以获得更多的文档、调用方法和使用细节。
| Name | Synopsis 简述 |
|---|---|
| go | go 程序管理 Go 源代码并运行这里列出的其他命令。有关使用细节,请参见该命令的文档。 |
| cgo | cgo 可以创建调用 C 代码的 Go 包。 |
| cover | cover 是一个用于创建和分析由 “go test -coverprofile” 生成的覆盖率配置文件的程序。 |
| fix | fix找到使用语言和库的旧特性的 Go 程序,并使用新特性重写它们。 |
| fmt | fmt 格式化 Go 包,它也可以作为独立的 gofmt 命令使用,具有更多通用选项。 |
| godoc | godoc 提取并生成 Go 包的文档。 |
| vet | vet 检查 Go 源代码并报告可疑的结构,例如实参与格式字符串不一致的 Printf 调用。 |
This is an abridged list. See the full command reference for documentation of the compilers and more.
这是一个简略的列表。请参阅完整的命令参考,了解编译器的文档和更多。
1.3.15 - go1
Go
Overview 概述
Go是一个管理Go源代码的工具。
用法:
|
|
这些命令(目前18个)是:
|
|
使用 “go help <command>“获得更多关于命令的信息。
其他帮助主题:
buildconstraint build constraints
buildmode build modes
c calling between Go and C
cache build and test caching
environment environment variables
filetype file types
go.mod the go.mod file
gopath GOPATH environment variable
gopath-get legacy GOPATH go get
goproxy module proxy protocol
importpath import path syntax
modules modules, module versions, and more
module-get module-aware go get
module-auth module authentication using go.sum
packages package lists and patterns
private configuration for downloading non-public code
testflag testing flags
testfunc testing functions
vcs controlling version control with GOVCS
使用 “go help <topic>“获得更多关于该主题的信息。
Start a bug report 开始一个bug报告
使用方法:
|
|
Bug打开默认的浏览器并启动一个新的错误报告。该报告包括有用的系统信息。
Compile packages and dependencies 编译包和依赖性
使用方法:
|
|
Build compiles the packages named by the import paths, along with their dependencies, but it does not install the results.
Build编译由导入路径命名的包,以及它们的依赖关系,但它并不安装这些结果。
If the arguments to build are a list of .go files from a single directory, build treats them as a list of source files specifying a single package.
如果 build 的参数是一个单一目录下的 .go 文件列表,build 会将其视为指定单一包的源文件列表。
When compiling packages, build ignores files that end in ‘_test.go’.
当编译包时,build 忽略了以 ‘_test.go’ 结尾的文件。
When compiling a single main package, build writes the resulting executable to an output file named after the first source file (‘go build ed.go rx.go’ writes ’ed’ or ’ed.exe’) or the source code directory (‘go build unix/sam’ writes ‘sam’ or ‘sam.exe’). The ‘.exe’ suffix is added when writing a Windows executable.
当编译一个主包时,build 将生成的可执行文件写入以第一个源文件命名的输出文件(‘go build ed.go rx.go’写’ed’或’ed.exe’)或源代码目录(‘go build unix/sam’ 写’sam’或’sam.exe’)。当编写Windows可执行文件时,会添加’.exe’后缀。
When compiling multiple packages or a single non-main package, build compiles the packages but discards the resulting object, serving only as a check that the packages can be built.
当编译多个包或单个非主包时,build 会编译这些包,但会丢弃生成的对象,只作为检查包是否可以被编译。
The -o flag forces build to write the resulting executable or object to the named output file or directory, instead of the default behavior described in the last two paragraphs. If the named output is an existing directory or ends with a slash or backslash, then any resulting executables will be written to that directory.
-o 标志强制 build 将生成的可执行文件或对象写入指定的输出文件或目录,而不是上两段中描述的默认行为。如果指定的输出是一个现有的目录,或者以斜线或反斜线结尾,那么任何结果的可执行文件都将被写入该目录。
The -i flag installs the packages that are dependencies of the target. The -i flag is deprecated. Compiled packages are cached automatically.
-i标志会安装作为目标依赖的包。-i标志已被弃用。编译的包会被自动缓存。
The build flags are shared by the build, clean, get, install, list, run, and test commands:
build、clean、get、install、list、run和test等命令都有的构建标志:
-a
force rebuilding of packages that are already up-to-date.
=> 强制重建已经是最新版本的包。
-n
print the commands but do not run them.
=> 打印命令但不运行它们。
-p n
the number of programs, such as build commands or test binaries, that can be run in parallel. The default is GOMAXPROCS, normally the number of CPUs available.
=> (可以并行运行的)程序数量,如构建命令或测试二进制文件,默认是GOMAXPROCS,通常是可用的CPU数量。
-race
enable data race detection.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64, darwin/arm64, windows/amd64,
linux/ppc64le and linux/arm64 (only for 48-bit VMA).
=> 启用数据竞争检测。
仅在linux/amd64、freebsd/amd64、darwin/amd64、darwin/arm64、windows/amd64、
linux/ppc64le和linux/arm64(仅支持48位VMA)上支持。
-msan
enable interoperation with memory sanitizer.
Supported only on linux/amd64, linux/arm64
and only with Clang/LLVM as the host C compiler.
On linux/arm64, pie build mode will be used.
=> 启用与内存净化器的互操作。
仅在linux/amd64、linux/arm64上支持,
并且仅在Clang/LLVM作为主机C编译器时支持。
在linux/arm64上,将使用pie构建模式。
-asan
enable interoperation with address sanitizer.
Supported only on linux/arm64, linux/amd64.
Supported only on linux/amd64 or linux/arm64 and only with GCC 7 and higher
or Clang/LLVM 9 and higher.
=> 启用与地址净化器的互操作。
仅在linux/arm64、linux/amd64上支持。
仅在linux/amd64或linux/arm64,和仅在GCC 7及以上版本中
或Clang/LLVM 9及以上版本上支持。
-v
print the names of packages as they are compiled.
=> 在编译过程中打印包的名称。
-work
print the name of the temporary work directory and
do not delete it when exiting.
=> 打印临时工作目录的名称,并且在退出时不删除它。
-x
print the commands.
=> 打印命令。
-asmflags '[pattern=]arg list'
arguments to pass on each go tool asm invocation.
=> 每次调用 "go tool asm" 时要传递的参数。
-buildmode mode
build mode to use. See 'go help buildmode' for more.
=> 使用的构建模式。参见'go help buildmode'了解更多。
-buildvcs
Whether to stamp binaries with version control information
("true", "false", or "auto"). By default ("auto"), version control
information is stamped into a binary if the main package, the main module
containing it, and the current directory are all in the same repository.
Use -buildvcs=false to always omit version control information, or
-buildvcs=true to error out if version control information is available but
cannot be included due to a missing tool or ambiguous directory structure.
=> 是否在二进制文件中加入版本控制信息("true","false",或 "auto")。
默认情况下("auto"),如果main包、包含它的主模块和当前目录都在同一个版本库中,
版本控制信息就会被压印到二进制文件中。
使用 -buildvcs=false 始终省略版本控制信息,
或者使用 -buildvcs=true 在版本控制信息可用但由于缺少工具或目录结构不明确而无法包含时出错。
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
=> 要使用的编译器名称,如runtime.Compiler(gccgo 或 gc)。
-gccgoflags '[pattern=]arg list'
arguments to pass on each gccgo compiler/linker invocation.
=> 每次调用gccgo编译器/链接器时要传递的参数。
-gcflags '[pattern=]arg list'
arguments to pass on each go tool compile invocation.
=> 在每次调用"go tool compile"要传递的参数。
-installsuffix suffix
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
or, if set explicitly, has _race appended to it. Likewise for the -msan
and -asan flags. Using a -buildmode option that requires non-default compile
flags has a similar effect.
=> 在包安装目录的名称中使用的后缀,以便使输出与默认构建分开。
如果使用 -race 标志,安装后缀会自动设置为race,
或者,如果明确设置,会有 _race 附加在它上面。
同样,-msan 和 -asan 标志也是如此。使用需要非默认编译标志的 -buildmode 选项也有类似效果。
-ldflags '[pattern=]arg list'
arguments to pass on each go tool link invocation.
=> 每次调用"go tool link"时要传递的参数。
-linkshared
build code that will be linked against shared libraries previously
created with -buildmode=shared.
=> 构建的代码将与之前用-buildmode=shared创建的共享库链接。
-mod mode
module download mode to use: readonly, vendor, or mod.
By default, if a vendor directory is present and the go version in go.mod
is 1.14 or higher, the go command acts as if -mod=vendor were set.
Otherwise, the go command acts as if -mod=readonly were set.
See https://golang.org/ref/mod#build-commands for details.
=> 要使用的模块下载模式:readonly、vendor 或 mod。
默认情况下,如果存在一个vendor目录,并且go.mod中的go版本是1.14或更高,go命令就像设置了-mod=vendor。
否则,go命令会像设置了 -mod=readonly 一样行事。
详见 https://golang.org/ref/mod#build-commands。
-modcacherw
leave newly-created directories in the module cache read-write
instead of making them read-only.
=> 将新创建的目录留在模块缓存中的读写位置,而不是让它们成为只读。
-modfile file
in module aware mode, read (and possibly write) an alternate go.mod
file instead of the one in the module root directory. A file named
"go.mod" must still be present in order to determine the module root
directory, but it is not accessed. When -modfile is specified, an
alternate go.sum file is also used: its path is derived from the
-modfile flag by trimming the ".mod" extension and appending ".sum".
=> 在模块感知模式下,读取(也可能写入)一个备用的go.mod文件,而不是模块根目录下的文件。
一个名为 "go.mod "的文件必须仍然存在,以确定模块根目录,但它不会被访问。
当-modfile被指定时,另一个go.Sum文件也被使用:它的路径由-modfile标志通过去掉".mod“扩展名和追加".sum"后缀名。
-overlay file
read a JSON config file that provides an overlay for build operations.
The file is a JSON struct with a single field, named 'Replace', that
maps each disk file path (a string) to its backing file path, so that
a build will run as if the disk file path exists with the contents
given by the backing file paths, or as if the disk file path does not
exist if its backing file path is empty. Support for the -overlay flag
has some limitations: importantly, cgo files included from outside the
include path must be in the same directory as the Go package they are
included from, and overlays will not appear when binaries and tests are
run through go run and go test respectively.
=> 读取一个JSON配置文件,为构建操作提供一个覆盖。
该文件是一个JSON结构,有一个名为 "Replace "的字段。 将每个磁盘文件路径(一个字符串)映射到其支持的文件路径,以便 构建将在磁盘文件路径存在的情况下运行,其内容为 的情况下运行,或者,如果磁盘文件路径的备份文件路径是 存在,如果它的支持文件路径是空的。对-overlay标志的支持 的支持有一些限制:重要的是,从include路径以外包含的cgo文件必须在同一目录下。包含路径之外的 cgo 文件必须与它们所包含的 Go 包在同一目录中,而且覆盖将不会 包括在同一目录中,而且当二进制文件和测试分别通过 go run 和 go test 运行时,覆盖不会出现 运行时,覆盖不会出现。
-pkgdir dir
install and load all packages from dir instead of the usual locations.
For example, when building with a non-standard configuration,
use -pkgdir to keep generated packages in a separate location.
=> 从 dir 安装并加载所有包,而不是通常的位置。例如,在使用非标准配置构建时。使用 -pkgdir 将生成的包保存在一个单独的位置。
-tags tag,list
a comma-separated list of additional build tags to consider satisfied
during the build. For more information about build tags, see
'go help buildconstraint'. (Earlier versions of Go used a
space-separated list, and that form is deprecated but still recognized.)
=> 逗号分隔的附加构建标签列表,以考虑在构建过程中满足 构建过程中要考虑满足的额外构建标签。关于构建标签的更多信息,见 'go help buildconstraint'。(早期版本的 Go 使用一个 空格分隔的列表,这种形式已被淘汰,但仍被认可)。
-trimpath
remove all file system paths from the resulting executable.
Instead of absolute file system paths, the recorded file names
will begin either a module path@version (when using modules),
or a plain import path (when using the standard library, or GOPATH).
=> 从生成的可执行文件中删除所有文件系统的路径。
取代绝对文件系统路径,记录的文件名 将以模块路径@版本开始(当使用模块时)。 或者一个普通的导入路径(当使用标准库或GOPATH时)。
-toolexec 'cmd args'
a program to use to invoke toolchain programs like vet and asm.
For example, instead of running asm, the go command will run
'cmd args /path/to/asm <arguments for asm>'.
The TOOLEXEC_IMPORTPATH environment variable will be set,
matching 'go list -f {{.ImportPath}}' for the package being built.
=> 一个用来调用工具链程序的程序,如vet和asm。
例如,代替运行asm,go命令将运行 'cmd args /path/to/asm < asm的参数>'。
TOOLEXEC_IMPORTPATH环境变量将被设置。
匹配'go list -f {{.ImportPath}}',用于正在构建的包。
The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a space-separated list of arguments to pass to an underlying tool during the build. To embed spaces in an element in the list, surround it with either single or double quotes. The argument list may be preceded by a package pattern and an equal sign, which restricts the use of that argument list to the building of packages matching that pattern (see ‘go help packages’ for a description of package patterns). Without a pattern, the argument list applies only to the packages named on the command line. The flags may be repeated with different patterns in order to specify different arguments for different sets of packages. If a package matches patterns given in multiple flags, the latest match on the command line wins. For example, ‘go build -gcflags=-S fmt’ prints the disassembly only for package fmt, while ‘go build -gcflags=all=-S fmt’ prints the disassembly for fmt and all its dependencies.
-asmflags、-gccgoflags、-gcflags和-ldflags标志接受一个用空格分隔的参数列表,在构建过程中传递给底层工具。要在列表中的某个元素中嵌入空格,可以用单引号或双引号将其包围。参数列表前面可以有一个包模式和一个等号,它将参数列表的使用限制在构建与该模式相匹配的包上(参见 “go help packages “中对包模式的描述)。如果没有模式,参数列表只适用于命令行上命名的包。这些标志可以用不同的模式重复使用,以便为不同的包组指定不同的参数。如果一个包与多个标志中给出的模式相匹配,命令行中最新的匹配将获胜。例如,“go build -gcflags=-S fmt “只打印包fmt的反汇编,而 “go build -gcflags=all=-S fmt “则打印fmt和它所有依赖项的反汇编。
For more about specifying packages, see ‘go help packages’. For more about where packages and binaries are installed, run ‘go help gopath’. For more about calling between Go and C/C++, run ‘go help c’.
更多关于指定包的信息,请参见’go help packages’。更多关于包和二进制文件的安装位置,运行’go help gopath’。更多关于Go和C/C++之间的调用,运行’go help c’。
Note: Build adheres to certain conventions such as those described by ‘go help gopath’. Not all projects can follow these conventions, however. Installations that have their own conventions or that use a separate software build system may choose to use lower-level invocations such as ‘go tool compile’ and ‘go tool link’ to avoid some of the overheads and design decisions of the build tool.
注意:Build遵守某些惯例,如’go help gopath’所描述的那些。然而,并不是所有的项目都能遵循这些约定。那些有自己的约定或者使用单独的软件构建系统的安装项目可以选择使用较低级别的调用,比如’go tool compile’和’go tool link’,以避免一些构建工具的开销和设计决定。
See also: go install, go get, go clean.
参见:go install、go get、go clean。
Remove object files and cached files 删除对象文件和缓存文件∥。
使用方法:
|
|
Clean removes object files from package source directories. The go command builds most objects in a temporary directory, so go clean is mainly concerned with object files left by other tools or by manual invocations of go build.
Clean从包源目录中删除对象文件。go命令在一个临时目录中构建大多数对象,所以go clean主要关注其他工具或手动调用go build时留下的对象文件。
If a package argument is given or the -i or -r flag is set, clean removes the following files from each of the source directories corresponding to the import paths:
如果给出了包的参数或设置了-i或-r标志,clean会从对应于导入路径的每个源目录中删除以下文件:
_obj/ old object directory, left from Makefiles
_test/ old test directory, left from Makefiles
_testmain.go old gotest file, left from Makefiles
test.out old test log, left from Makefiles
build.out old test log, left from Makefiles
*.[568ao] object files, left from Makefiles
DIR(.exe) from go build
DIR.test(.exe) from go test -c
MAINFILE(.exe) from go build MAINFILE.go
*.so from SWIG
In the list, DIR represents the final path element of the directory, and MAINFILE is the base name of any Go source file in the directory that is not included when building the package.
在列表中,DIR代表目录的最后一个路径元素,MAINFILE是该目录中任何在构建包时未包含的Go源代码文件的基本名称。
The -i flag causes clean to remove the corresponding installed archive or binary (what ‘go install’ would create).
-i 标志使 clean 移除相应的已安装的归档文件或二进制文件(“go install “会创建)。
The -n flag causes clean to print the remove commands it would execute, but not run them.
n标志使clean打印它将执行的删除命令,但不运行它们。
The -r flag causes clean to be applied recursively to all the dependencies of the packages named by the import paths.
-r 标志使 clean 递归地应用于由导入路径命名的包的所有依赖关系。
The -x flag causes clean to print remove commands as it executes them.
-x标志使clean在执行删除命令时打印这些命令。
The -cache flag causes clean to remove the entire go build cache.
-cache 标志使 clean 移除整个 go build 缓存。
The -testcache flag causes clean to expire all test results in the go build cache.
-testcache标志使clean在go build cache中过期所有的测试结果。
The -modcache flag causes clean to remove the entire module download cache, including unpacked source code of versioned dependencies.
-modcache标志使clean删除整个模块下载缓存,包括版本依赖的未打包的源代码。
The -fuzzcache flag causes clean to remove files stored in the Go build cache for fuzz testing. The fuzzing engine caches files that expand code coverage, so removing them may make fuzzing less effective until new inputs are found that provide the same coverage. These files are distinct from those stored in testdata directory; clean does not remove those files.
-fuzzcache标志使clean删除存储在Go build cache中的文件,用于模糊测试。模糊测试引擎缓存了扩大代码覆盖率的文件,因此删除这些文件可能会降低模糊测试的效率,直到找到能提供相同覆盖率的新输入。这些文件与存储在testdata目录中的文件不同;clean不会删除这些文件。
For more about build flags, see ‘go help build’.
关于构建标志的更多信息,请参见 “go help build”。
For more about specifying packages, see ‘go help packages’.
更多关于指定包的信息,请参见 “go help packages”。
Show documentation for package or symbol 显示包或符号的文档
使用方法:
|
|
Doc prints the documentation comments associated with the item identified by its arguments (a package, const, func, type, var, method, or struct field) followed by a one-line summary of each of the first-level items “under” that item (package-level declarations for a package, methods for a type, etc.).
文档打印与参数标识的项目(包、const、func、类型、var、方法或结构域)相关的文档注释,然后是该项目 “下 “的每个一级项目(包的包级声明、类型的方法,等等)的单行摘要。
Doc accepts zero, one, or two arguments.
Doc接受零、一或两个参数。
Given no arguments, that is, when run as
在没有参数的情况下,也就是说,当运行为
|
|
it prints the package documentation for the package in the current directory. If the package is a command (package main), the exported symbols of the package are elided from the presentation unless the -cmd flag is provided.
时,它会打印出当前目录下的包的文档。如果包是一个命令(包main),除非提供了-cmd标志,否则包的导出符号将从演示中省略。
When run with one argument, the argument is treated as a Go-syntax-like representation of the item to be documented. What the argument selects depends on what is installed in GOROOT and GOPATH, as well as the form of the argument, which is schematically one of these:
当运行时有一个参数,该参数被视为要记录的项目的类似Go-syntax的表述。参数选择的内容取决于GOROOT和GOPATH中安装的内容,以及参数的形式,从图上看是其中之一:
|
|
The first item in this list matched by the argument is the one whose documentation is printed. (See the examples below.) However, if the argument starts with a capital letter it is assumed to identify a symbol or method in the current directory.
这个列表中由参数匹配的第一个项目是其文档被打印的项目。(见下面的例子。)然而,如果参数以大写字母开头,则假定它是指当前目录中的一个符号或方法。
For packages, the order of scanning is determined lexically in breadth-first order. That is, the package presented is the one that matches the search and is nearest the root and lexically first at its level of the hierarchy. The GOROOT tree is always scanned in its entirety before GOPATH.
对于包来说,扫描的顺序是按广度第一的顺序来确定的。也就是说,所呈现的包是与搜索相匹配的,并且是离根最近的,在其层次结构中词法第一的。GOROOT树总是在GOPATH之前被完整地扫描。
If there is no package specified or matched, the package in the current directory is selected, so “go doc Foo” shows the documentation for symbol Foo in the current package.
如果没有指定或匹配的包,则选择当前目录下的包,所以 “go doc Foo “显示当前包中符号Foo的文档。
The package path must be either a qualified path or a proper suffix of a path. The go tool’s usual package mechanism does not apply: package path elements like . and … are not implemented by go doc.
包的路径必须是一个合格的路径或者是一个路径的适当后缀。go工具通常的包机制并不适用:像.和…这样的包路径元素并没有被go doc实现。
When run with two arguments, the first is a package path (full path or suffix), and the second is a symbol, or symbol with method or struct field:
当运行时有两个参数,第一个是包的路径(完整的路径或后缀),第二个是一个符号,或带有方法或结构域的符号:
|
|
In all forms, when matching symbols, lower-case letters in the argument match either case but upper-case letters match exactly. This means that there may be multiple matches of a lower-case argument in a package if different symbols have different cases. If this occurs, documentation for all matches is printed.
在所有形式中,当匹配符号时,参数中的小写字母可以匹配任何一种情况,但大写字母则完全匹配。这意味着,如果不同的符号有不同的大小写,在一个包中可能有多个小写参数的匹配。如果发生这种情况,将打印所有匹配的文档。
Examples:
例子
|
|
Flags:
标志
-all
Show all the documentation for the package. 显示该包的所有文档。
-c
Respect case when matching symbols. 匹配符号时尊重大小写。
-cmd
Treat a command (package main) like a regular package.
Otherwise package main's exported symbols are hidden
when showing the package's top-level documentation.
像对待普通包一样对待一个命令(package main)。
否则包main的输出符号会在显示包的顶层文档时被隐藏
当显示包的顶层文档时。
-short
One-line representation for each symbol.
每个符号的单行表示。
-src
Show the full source code for the symbol. This will
display the full Go source of its declaration and
definition, such as a function definition (including
the body), type declaration or enclosing const
block. The output may therefore include unexported
details.
显示该符号的完整源代码。这将
显示其声明和定义的完整Go源码
定义的全部围棋源代码,例如函数定义(包括
体)、类型声明或封闭的 const
块。因此,输出可能包括未输出的
细节。
-u
Show documentation for unexported as well as exported
symbols, methods, and fields.
显示未导出的以及已导出的
符号、方法和字段。
Print Go environment information 打印Go环境信息
使用方法:
|
|
Env prints Go environment information.
Env可以打印围棋环境信息。
By default env prints information as a shell script (on Windows, a batch file). If one or more variable names is given as arguments, env prints the value of each named variable on its own line.
默认情况下,env以shell脚本的形式打印信息(在Windows下为批处理文件)。如果一个或多个变量名作为参数,env会在自己的行中打印出每个变量的值。
The -json flag prints the environment in JSON format instead of as a shell script.
-json标志将环境打印成JSON格式,而不是作为一个shell脚本。
The -u flag requires one or more arguments and unsets the default setting for the named environment variables, if one has been set with ‘go env -w’.
-u标志需要一个或多个参数,并且取消指定环境变量的默认设置,如果已经用 “go env -w “设置了一个环境变量的话。
The -w flag requires one or more arguments of the form NAME=VALUE and changes the default settings of the named environment variables to the given values.
-w标志需要一个或多个参数,其形式为NAME=VALUE,并将命名的环境变量的默认设置改为给定的值。
For more about environment variables, see ‘go help environment’.
关于环境变量的更多信息,请参见’go help environment’。
Update packages to use new APIs 更新包以使用新的API
使用方法:
|
|
Fix runs the Go fix command on the packages named by the import paths.
Fix在导入路径命名的包上运行Go fix命令。
The -fix flag sets a comma-separated list of fixes to run. The default is all known fixes. (Its value is passed to ‘go tool fix -r’.)
-fix标志设置了一个以逗号分隔的修复列表,以便运行。默认是所有已知的修复。(它的值会传递给’go tool fix -r’)。
For more about fix, see ‘go doc cmd/fix’. For more about specifying packages, see ‘go help packages’.
关于fix的更多信息,见 “go doc cmd/fix”。关于指定包的更多信息,请参见 “go help packages”。
To run fix with other options, run ‘go tool fix’.
要用其他选项运行fix,请运行’go tool fix’。
See also: go fmt, go vet.
另见:go fmt,go vet。
Gofmt (reformat) package sources Gofmt(重新格式化)包的来源
使用方法:
|
|
Fmt runs the command ‘gofmt -l -w’ on the packages named by the import paths. It prints the names of the files that are modified.
Fmt对导入路径命名的包运行’gofmt -l -w’命令。它打印出被修改的文件的名称。
For more about gofmt, see ‘go doc cmd/gofmt’. For more about specifying packages, see ‘go help packages’.
关于gofmt的更多信息,见’go doc cmd/gofmt’。关于指定包的更多信息,见’go help packages’。
The -n flag prints commands that would be executed. The -x flag prints commands as they are executed.
-n 标志打印将被执行的命令。-x标志在命令被执行时打印它们。
The -mod flag’s value sets which module download mode to use: readonly or vendor. See ‘go help modules’ for more.
-mod标志的值设置使用哪种模块下载模式:只读或供应商。更多信息见 “go help modules”。
To run gofmt with specific options, run gofmt itself.
要用特定的选项运行gofmt,请运行gofmt本身。
See also: go fix, go vet.
参见:go fix, go vet。
Generate Go files by processing source 通过处理源代码生成Go文件
使用方法:
|
|
Generate runs commands described by directives within existing files. Those commands can run any process but the intent is to create or update Go source files.
Generate运行现有文件中指令描述的命令。这些命令可以运行任何进程,但其目的是创建或更新 Go 源文件。
Go generate is never run automatically by go build, go test, and so on. It must be run explicitly.
Go generate不会被go build、go test等自动运行。它必须明确地运行。
Go generate scans the file for directives, which are lines of the form,
Go generate 会扫描文件中的指令,这些指令的形式是。
|
|
(note: no leading spaces and no space in “//go”) where command is the generator to be run, corresponding to an executable file that can be run locally. It must either be in the shell path (gofmt), a fully qualified path (/usr/you/bin/mytool), or a command alias, described below.
(注意:没有前导空格,”//go “中也没有空格),其中命令是要运行的生成器,对应于一个可执行文件,可以在本地运行。它必须在shell路径中(gofmt),一个完全限定的路径(/usr/you/bin/mytool),或者一个命令别名,如下所述。
Note that go generate does not parse the file, so lines that look like directives in comments or multiline strings will be treated as directives.
注意,go generate并不解析文件,所以在注释或多行字符串中看起来像指令的行将被视为指令。
The arguments to the directive are space-separated tokens or double-quoted strings passed to the generator as individual arguments when it is run.
指令的参数是空格分隔的标记或双引号字符串,在运行时作为单独的参数传递给生成器。
Quoted strings use Go syntax and are evaluated before execution; a quoted string appears as a single argument to the generator.
带引号的字符串使用Go语法,并在执行前被评估;带引号的字符串作为一个单独的参数出现在生成器中。
To convey to humans and machine tools that code is generated, generated source should have a line that matches the following regular expression (in Go syntax):
为了向人类和机器工具传达代码是生成的,生成的源代码应该有一行与以下正则表达式相匹配(用Go语法):
^// Code generated .* DO NOT EDIT\.$
This line must appear before the first non-comment, non-blank text in the file.
这一行必须出现在文件中第一个非注释、非空白文本之前。
Go generate sets several variables when it runs the generator:
Go generate在运行生成器时设置了几个变量:
$GOARCH
The execution architecture (arm, amd64, etc.)
$GOOS
The execution operating system (linux, windows, etc.)
$GOFILE
The base name of the file.
$GOLINE
The line number of the directive in the source file.
$GOPACKAGE
The name of the package of the file containing the directive.
$GOROOT
The GOROOT directory for the 'go' command that invoked the
generator, containing the Go toolchain and standard library.
$DOLLAR
A dollar sign.
Other than variable substitution and quoted-string evaluation, no special processing such as “globbing” is performed on the command line.
除了变量替换和加引号的字符串评估外,在命令行上不进行任何特殊处理,如 “球化”。
As a last step before running the command, any invocations of any environment variables with alphanumeric names, such as $GOFILE or $HOME, are expanded throughout the command line. The syntax for variable expansion is $NAME on all operating systems. Due to the order of evaluation, variables are expanded even inside quoted strings. If the variable NAME is not set, $NAME expands to the empty string.
作为运行命令前的最后一步,任何调用字母数字名称的环境变量,如$GOFILE或$HOME,都会在整个命令行中展开。变量扩展的语法在所有操作系统上都是$NAME。由于计算顺序的关系,即使在带引号的字符串中,变量也会被展开。如果没有设置变量NAME,$NAME将扩展为空字符串。
A directive of the form,
以下形式的指令,
//go:generate -command xxx args...
specifies, for the remainder of this source file only, that the string xxx represents the command identified by the arguments. This can be used to create aliases or to handle multiword generators. For example,
的指令指定,仅在本源文件的剩余部分,字符串xxx代表由参数确定的命令。这可以用来创建别名或处理多字生成器。例如。
//go:generate -command foo go tool foo
specifies that the command “foo” represents the generator “go tool foo”.
指定命令 “foo “代表生成器 “go tool foo”。
Generate processes packages in the order given on the command line, one at a time. If the command line lists .go files from a single directory, they are treated as a single package. Within a package, generate processes the source files in a package in file name order, one at a time. Within a source file, generate runs generators in the order they appear in the file, one at a time. The go generate tool also sets the build tag “generate” so that files may be examined by go generate but ignored during build.
生成器按照命令行给出的顺序,一次一个地处理包。如果命令行列出了一个目录下的.go文件,它们会被当作一个包来处理。在一个包中,generate按照文件名的顺序,一次一个地处理包中的源文件。在一个源文件中,generate按照文件中出现的顺序,一次一个地运行生成器。go generate工具还设置了构建标签 “generate”,以便文件可以被go generate检查,但在构建过程中被忽略。
For packages with invalid code, generate processes only source files with a valid package clause.
对于有无效代码的包,generate只处理有有效包条款的源文件。
If any generator returns an error exit status, “go generate” skips all further processing for that package.
如果任何生成器返回错误的退出状态,“go generate “将跳过对该包的所有进一步处理。
The generator is run in the package’s source directory.
生成器在包的源代码目录下运行。
Go generate accepts one specific flag:
Go generate接受一个特定的标志:
-run=""
if non-empty, specifies a regular expression to select
directives whose full original source text (excluding
any trailing spaces and final newline) matches the
expression.
It also accepts the standard build flags including -v, -n, and -x. The -v flag prints the names of packages and files as they are processed. The -n flag prints commands that would be executed. The -x flag prints commands as they are executed.
它也接受标准的编译标志,包括-v、-n和-x。-v标志在处理包和文件时打印它们的名字。n标志打印将被执行的命令。-x标志在命令被执行时打印它们。
For more about build flags, see ‘go help build’.
关于构建标志的更多信息,见 “go help build”:
For more about specifying packages, see ‘go help packages’.
关于指定包的更多信息,见’go help packages’:
Add dependencies to current module and install them 将依赖关系添加到当前模块并安装它们
使用方法:
|
|
Get resolves its command-line arguments to packages at specific module versions, updates go.mod to require those versions, and downloads source code into the module cache.
get将其命令行参数解析为特定模块版本的包,更新go.mod以要求这些版本,并下载源代码到模块缓存中。
To add a dependency for a package or upgrade it to its latest version:
要添加一个包的依赖关系或将其升级到最新版本:
|
|
To upgrade or downgrade a package to a specific version:
要将一个包升级或降级到一个特定的版本:
|
|
To remove a dependency on a module and downgrade modules that require it:
要删除一个模块的依赖关系和降级需要它的模块:
|
|
See https://golang.org/ref/mod#go-get for details.
详见https://golang.org/ref/mod#go-get。
In earlier versions of Go, ‘go get’ was used to build and install packages. Now, ‘go get’ is dedicated to adjusting dependencies in go.mod. ‘go install’ may be used to build and install commands instead. When a version is specified, ‘go install’ runs in module-aware mode and ignores the go.mod file in the current directory. For example:
在Go的早期版本中,‘go get’被用来构建和安装包。现在,‘go get’专门用来调整go.mod中的依赖关系。‘go install’可以用来代替构建和安装命令。当指定一个版本时,‘go install’在模块感知模式下运行,忽略当前目录下的go.mod文件。比如说:
|
|
See ‘go help install’ or https://golang.org/ref/mod#go-install for details.
详情见’go help install’或https://golang.org/ref/mod#go-install。
‘go get’ accepts the following flags.
go get “接受以下标志。
The -t flag instructs get to consider modules needed to build tests of packages specified on the command line.
-t 标志指示 get 考虑构建测试命令行上指定的包所需的模块。
The -u flag instructs get to update modules providing dependencies of packages named on the command line to use newer minor or patch releases when available.
u 标志指示 get 更新提供命令行上指定的包的依赖性的模块,以使用较新的次要或补丁版本。
The -u=patch flag (not -u patch) also instructs get to update dependencies, but changes the default to select patch releases.
-u=patch 标志(不是 -u patch)也指示 get 更新依赖关系,但改变了默认的选择补丁版本。
When the -t and -u flags are used together, get will update test dependencies as well.
当-t和-u标志一起使用时,get也会更新测试依赖。
The -x flag prints commands as they are executed. This is useful for debugging version control commands when a module is downloaded directly from a repository.
-x标志在执行时打印命令。当一个模块直接从版本库下载时,这对调试版本控制命令很有用。
For more about modules, see https://golang.org/ref/mod.
关于模块的更多信息,见https://golang.org/ref/mod。
For more about specifying packages, see ‘go help packages’.
关于指定包的更多信息,见’go help packages’。
This text describes the behavior of get using modules to manage source code and dependencies. If instead the go command is running in GOPATH mode, the details of get’s flags and effects change, as does ‘go help get’. See ‘go help gopath-get’.
这段文字描述了使用模块来管理源代码和依赖关系的get的行为。如果go命令是在GOPATH模式下运行,get的标志和效果的细节就会改变,‘go help get’也是如此。参见 “go help gopath-get”。
See also: go build, go install, go clean, go mod.
另见:go build、go install、go clean、go mod。
Compile and install packages and dependencies 编译和安装包和依赖项
使用方法:
|
|
Install compiles and installs the packages named by the import paths.
安装编译并安装由导入路径命名的包。
Executables are installed in the directory named by the GOBIN environment variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set. Executables in $GOROOT are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
可执行文件被安装在由GOBIN环境变量命名的目录中,如果没有设置GOPATH环境变量,则默认为$GOPATH/bin或$HOME/go/bin。$GOROOT中的可执行文件会安装在$GOROOT/bin或$GOTOOLDIR中,而不是$GOBIN。
If the arguments have version suffixes (like @latest or @v1.0.0), “go install” builds packages in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for installing executables without affecting the dependencies of the main module. To eliminate ambiguity about which module versions are used in the build, the arguments must satisfy the following constraints:
如果参数有版本后缀(如@latest或@v1.0.0),“go install “将以模块感知模式构建包,忽略当前目录或任何父目录中的go.mod文件,如果有的话。这对于安装可执行文件而不影响主模块的依赖关系很有用。为了消除在构建中使用哪些模块版本的歧义,参数必须满足以下限制。
- Arguments must be package paths or package patterns (with “…” wildcards). They must not be standard packages (like fmt), meta-patterns (std, cmd, all), or relative or absolute file paths.
- 参数必须是包路径或包模式(有”… “通配符)。它们不能是标准包(如fmt)、元模式(std、cmd、all)或相对或绝对文件路径。
- All arguments must have the same version suffix. Different queries are not allowed, even if they refer to the same version.
- 所有参数必须有相同的版本后缀。不同的查询是不允许的,即使它们引用的是同一个版本。
- All arguments must refer to packages in the same module at the same version.
- 所有参数必须引用同一模块中同一版本的包。
- Package path arguments must refer to main packages. Pattern arguments will only match main packages.
- 包路径参数必须指的是主包。模式参数将只匹配主包。
- No module is considered the “main” module. If the module containing packages named on the command line has a go.mod file, it must not contain directives (replace and exclude) that would cause it to be interpreted differently than if it were the main module. The module must not require a higher version of itself.
- 没有模块被认为是 “主 “模块。如果包含命令行上命名的包的模块有一个go.mod文件,它不能包含指令(替换和排除),这将导致它的解释与主模块不同。该模块不能要求自己有更高的版本。
- Vendor directories are not used in any module. (Vendor directories are not included in the module zip files downloaded by ‘go install’.)
- 在任何模块中都不使用供应商目录。(供应商目录不包括在’go install’下载的模块压缩文件中)。
If the arguments don’t have version suffixes, “go install” may run in module-aware mode or GOPATH mode, depending on the GO111MODULE environment variable and the presence of a go.mod file. See ‘go help modules’ for details. If module-aware mode is enabled, “go install” runs in the context of the main module.
如果参数没有版本后缀,“go install “可能在模块感知模式或GOPATH模式下运行,这取决于GO111MODULE环境变量和go.mod文件的存在。详情见 “go help modules”。如果启用了模块感知模式,“go install “将在主模块的上下文中运行。
When module-aware mode is disabled, other packages are installed in the directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled, other packages are built and cached but not installed.
当模块感知模式被禁用时,其他包被安装在$GOPATH/pkg/$GOOS_$GOARCH目录下。当模块感知模式被启用时,其他包被构建和缓存,但不安装。
The -i flag installs the dependencies of the named packages as well. The -i flag is deprecated. Compiled packages are cached automatically.
-i 标志也会安装指定包的依赖项。-i 标志已被弃用。编译的包会被自动缓存。
For more about the build flags, see ‘go help build’. For more about specifying packages, see ‘go help packages’.
关于构建标志的更多信息,请参见’go help build’。更多关于指定包的信息,请看’go help packages’。
See also: go build, go get, go clean.
另见:go build,go get,go clean。
List packages or modules 列出包或模块
使用方法:
|
|
List lists the named packages, one per line. The most commonly-used flags are -f and -json, which control the form of the output printed for each package. Other list flags, documented below, control more specific details.
List列出了命名的包,每行一个。最常用的标志是 -f 和 -json,它们控制每个包的输出形式。其他的列表标志,如下文所述,控制更具体的细节。
The default output shows the package import path:
默认输出显示包的导入路径:
bytes
encoding/json
github.com/gorilla/mux
golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the syntax of package template. The default output is equivalent to -f ‘{{.ImportPath}}’. The struct being passed to the template is:
-f标志指定了列表的另一种格式,使用包模板的语法。默认输出相当于-f ‘{{.ImportPath}}。被传递给模板的结构是:
|
|
Packages stored in vendor directories report an ImportPath that includes the path to the vendor directory (for example, “d/vendor/p” instead of “p”), so that the ImportPath uniquely identifies a given copy of a package. The Imports, Deps, TestImports, and XTestImports lists also contain these expanded import paths. See golang.org/s/go15vendor for more about vendoring.
存储在供应商目录中的包报告一个ImportPath,其中包括供应商目录的路径(例如,“d/vendor/p “而不是 “p”),这样ImportPath就能唯一地识别一个包的特定副本。Imports、Deps、TestImports和XTestImports列表也包含这些扩展的导入路径。参见 golang.org/s/go15vendor 了解更多关于 vendoring 的信息。
The error information, if any, is
错误信息,如果有的话,是
|
|
The module information is a Module struct, defined in the discussion of list -m below.
模块信息是一个模块结构,在下面关于list -m的讨论中定义。
The template function “join” calls strings.Join.
模板函数 “join “调用 strings.Join。
The template function “context” returns the build context, defined as:
模板函数 “context “返回构建上下文,定义如下。
|
|
For more information about the meaning of these fields see the documentation for the go/build package’s Context type.
关于这些字段含义的更多信息,请参见go/build包的Context类型文档。
The -json flag causes the package data to be printed in JSON format instead of using the template format. The JSON flag can optionally be provided with a set of comma-separated required field names to be output. If so, those required fields will always appear in JSON output, but others may be omitted to save work in computing the JSON struct.
-json标志使包的数据以JSON格式打印,而不是使用模板格式。JSON标志可以选择提供一组用逗号分隔的所需字段名来输出。如果是这样,这些必需的字段将总是出现在JSON输出中,但其他字段可以省略,以节省计算JSON结构的工作。
The -compiled flag causes list to set CompiledGoFiles to the Go source files presented to the compiler. Typically this means that it repeats the files listed in GoFiles and then also adds the Go code generated by processing CgoFiles and SwigFiles. The Imports list contains the union of all imports from both GoFiles and CompiledGoFiles.
-compiled 标志使 list 将 CompiledGoFiles 设置为提交给编译器的 Go 源文件。通常这意味着它重复 GoFiles 中列出的文件,然后还添加处理 CgoFiles 和 SwigFiles 产生的 Go 代码。Imports 列表包含了从 GoFiles 和 CompiledGoFiles 中导入的所有文件。
The -deps flag causes list to iterate over not just the named packages but also all their dependencies. It visits them in a depth-first post-order traversal, so that a package is listed only after all its dependencies. Packages not explicitly listed on the command line will have the DepOnly field set to true.
-deps 标志使 list 不仅遍历命名的包,而且还遍历它们的所有依赖项。它以深度优先的后序遍历方式访问它们,因此一个包只在其所有依赖关系之后才被列出。在命令行中没有明确列出的包,其DepOnly字段将被设置为true。
The -e flag changes the handling of erroneous packages, those that cannot be found or are malformed. By default, the list command prints an error to standard error for each erroneous package and omits the packages from consideration during the usual printing. With the -e flag, the list command never prints errors to standard error and instead processes the erroneous packages with the usual printing. Erroneous packages will have a non-empty ImportPath and a non-nil Error field; other information may or may not be missing (zeroed).
-e 标志改变了对错误包的处理,即那些找不到的或格式不正确的包。默认情况下,list 命令会对每个错误的包打印一个错误到标准错误,并在通常的打印过程中省略这些包。如果使用 -e 标志,list 命令就不会将错误打印到标准错误中,而是用通常的打印方式处理错误的包。错误的包会有一个非空的 ImportPath 和一个非零的 Error 字段;其他信息可能会或不会丢失(归零)。
The -export flag causes list to set the Export field to the name of a file containing up-to-date export information for the given package, and the BuildID field to the build ID of the compiled package.
-export 标志使 list 将 Export 字段设置为包含给定包的最新导出信息的文件名,将 BuildID 字段设置为编译包的构建 ID。
The -find flag causes list to identify the named packages but not resolve their dependencies: the Imports and Deps lists will be empty.
-find 标志使 list 识别指定的包,但不解决它们的依赖关系:Imports 和 Deps 列表将为空。
The -test flag causes list to report not only the named packages but also their test binaries (for packages with tests), to convey to source code analysis tools exactly how test binaries are constructed. The reported import path for a test binary is the import path of the package followed by a “.test” suffix, as in “math/rand.test”. When building a test, it is sometimes necessary to rebuild certain dependencies specially for that test (most commonly the tested package itself). The reported import path of a package recompiled for a particular test binary is followed by a space and the name of the test binary in brackets, as in “math/rand math/rand.test” or “regexp [sort.test]”. The ForTest field is also set to the name of the package being tested (“math/rand” or “sort” in the previous examples).
-test 标志使 list 不仅报告命名的包,而且报告它们的测试二进制文件(对于有测试的包),以便向源代码分析工具准确传达测试二进制文件是如何构建的。报告的测试二进制文件的导入路径是包的导入路径,后面加一个”.test “的后缀,如 “math/rand.test”。当构建一个测试时,有时需要专门为该测试重建某些依赖项(最常见的是被测包本身)。为特定测试二进制文件重新编译的包的报告导入路径后面是一个空格和括号中的测试二进制文件的名称,如 “math/rand math/rand.test “或 “regexp [sort.test]” 。ForTest字段也被设置为被测试包的名称(在前面的例子中为 “math/rand “或 “sort”)。
The Dir, Target, Shlib, Root, ConflictDir, and Export file paths are all absolute paths.
Dir、Target、Shlib、Root、ConflictDir和Export文件路径都是绝对路径。
By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir (that is, paths relative to Dir, not absolute paths). The generated files added when using the -compiled and -test flags are absolute paths referring to cached copies of generated Go source files. Although they are Go source files, the paths may not end in “.go”.
默认情况下,GoFiles、CgoFiles等列表持有Dir中的文件名(即相对于Dir的路径,而不是绝对路径)。使用 -compiled 和 -test 标志时添加的生成文件是绝对路径,指的是生成的 Go 源文件的缓存副本。虽然它们是 Go 源文件,但路径可能不是以 “.go” 结尾。
The -m flag causes list to list modules instead of packages.
-m 标志使 list 列出模块而不是包。
When listing modules, the -f flag still specifies a format template applied to a Go struct, but now a Module struct:
当列出模块时,-f 标志仍然指定应用于 Go 结构的格式模板,但现在是一个 Module 结构:
|
|
The file GoMod refers to may be outside the module directory if the module is in the module cache or if the -modfile flag is used.
如果模块在模块缓存中或使用了-modfile标志,GoMod所指的文件可能在模块目录之外。
The default output is to print the module path and then information about the version and replacement if any. For example, ‘go list -m all’ might print:
默认输出是打印模块路径,然后是版本和替换信息(如果有)。例如,“go list -m all “可能会打印:
my/main/module
golang.org/x/text v0.3.0 => /tmp/text
rsc.io/pdf v0.1.1
The Module struct has a String method that formats this line of output, so that the default format is equivalent to -f ‘{{.String}}’.
模块结构有一个String方法来格式化这一行的输出,所以默认格式相当于-f ‘{{.String}}。
Note that when a module has been replaced, its Replace field describes the replacement module, and its Dir field is set to the replacement’s source code, if present. (That is, if Replace is non-nil, then Dir is set to Replace.Dir, with no access to the replaced source code.)
注意,当一个模块被替换时,它的Replace字段描述了替换的模块,它的Dir字段被设置为替换的源代码,如果存在的话。(也就是说,如果Replace不是nil,那么Dir被设置为Replace.Dir,不能访问被替换的源代码。)
The -u flag adds information about available upgrades. When the latest version of a given module is newer than the current one, list -u sets the Module’s Update field to information about the newer module. list -u will also set the module’s Retracted field if the current version is retracted. The Module’s String method indicates an available upgrade by formatting the newer version in brackets after the current version. If a version is retracted, the string “(retracted)” will follow it. For example, ‘go list -m -u all’ might print:
-u标志增加了关于可用升级的信息。当给定模块的最新版本比当前版本新时,list -u 将模块的 Update 字段设置为较新模块的信息。如果当前版本被收回,list -u 也将设置模块的 Retracted 字段。Module的String方法通过在当前版本后的括号中格式化较新的版本来表示可用的升级。如果一个版本被收回,字符串”(retracted) “将跟随它。例如,“go list -m -u all “可能会打印:
my/main/module
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 (retracted) [v0.1.2]
(For tools, ‘go list -m -u -json all’ may be more convenient to parse.)
(对于工具,‘go list -m -u -json all’可能更方便解析)。
The -versions flag causes list to set the Module’s Versions field to a list of all known versions of that module, ordered according to semantic versioning, earliest to latest. The flag also changes the default output format to display the module path followed by the space-separated version list.
-versions 标志使 list 将 Module 的 Versions 字段设置为该模块的所有已知版本的列表,按照语义版本排序,从最早到最新。该标志还改变了默认的输出格式,显示模块的路径,然后是用空格分隔的版本列表。
The -retracted flag causes list to report information about retracted module versions. When -retracted is used with -f or -json, the Retracted field will be set to a string explaining why the version was retracted. The string is taken from comments on the retract directive in the module’s go.mod file. When -retracted is used with -versions, retracted versions are listed together with unretracted versions. The -retracted flag may be used with or without -m.
-retracted 标志使 list 报告关于缩减的模块版本的信息。当 -retracted 与 -f 或 -json 一起使用时,Retracted 字段将被设置为一个字符串,解释该版本被撤回的原因。这个字符串来自模块go.mod文件中retractive指令的注释。当-retracted与-versions一起使用时,撤回的版本会与未撤回的版本一起列出。-retracted标志可以和-m一起使用,也可以不使用。
The arguments to list -m are interpreted as a list of modules, not packages. The main module is the module containing the current directory. The active modules are the main module and its dependencies. With no arguments, list -m shows the main module. With arguments, list -m shows the modules specified by the arguments. Any of the active modules can be specified by its module path. The special pattern “all” specifies all the active modules, first the main module and then dependencies sorted by module path. A pattern containing “…” specifies the active modules whose module paths match the pattern. A query of the form path@version specifies the result of that query, which is not limited to active modules. See ‘go help modules’ for more about module queries.
list -m的参数被解释为一个模块的列表,而不是包的列表。主模块是包含当前目录的模块。活动模块是主模块和它的依赖关系。没有参数时,list -m 显示主模块。有参数时,list -m 显示由参数指定的模块。任何一个活动模块都可以通过其模块路径指定。特殊模式 “all “指定所有活动模块,首先是主模块,然后是按模块路径排序的依赖模块。包含”… “的模式指定模块路径与该模式相匹配的活动模块。path@version形式的查询指定了该查询的结果,它不限于活动模块。关于模块查询的更多信息,见 “go help modules”。
The template function “module” takes a single string argument that must be a module path or query and returns the specified module as a Module struct. If an error occurs, the result will be a Module struct with a non-nil Error field.
模板函数 “module “接收一个字符串参数,该参数必须是模块路径或查询,并将指定的模块作为Module结构返回。如果发生错误,结果将是一个带有非零错误字段的模块结构。
When using -m, the -reuse=old.json flag accepts the name of file containing the JSON output of a previous ‘go list -m -json’ invocation with the same set of modifier flags (such as -u, -retracted, and -versions). The go command may use this file to determine that a module is unchanged since the previous invocation and avoid redownloading information about it. Modules that are not redownloaded will be marked in the new output by setting the Reuse field to true. Normally the module cache provides this kind of reuse automatically; the -reuse flag can be useful on systems that do not preserve the module cache.
当使用-m时,-reuse=old.json标志接受包含先前’go list -m -json’调用的JSON输出的文件名,其修改标志(如-u,-retracted,和-versions)相同。go命令可以使用这个文件来确定某个模块自上次调用后没有变化,并避免重新下载该模块的信息。没有被重新下载的模块将在新的输出中通过将Reuse字段设置为true来标记。通常情况下,模块缓存会自动提供这种重用;-reuse标志在不保留模块缓存的系统上可能很有用。
For more about build flags, see ‘go help build’.
关于构建标志的更多信息,见 “go help build”。
For more about specifying packages, see ‘go help packages’.
更多关于指定包的信息,请参见’go help packages’。
For more about modules, see https://golang.org/ref/mod.
关于模块的更多信息,见https://golang.org/ref/mod。
Module maintenance 模块维护
Go mod provides access to operations on modules.
Go mod提供了对模块操作的访问。
Note that support for modules is built into all the go commands, not just ‘go mod’. For example, day-to-day adding, removing, upgrading, and downgrading of dependencies should be done using ‘go get’. See ‘go help modules’ for an overview of module functionality.
注意,对模块的支持是建立在所有go命令中的,而不仅仅是 “go mod”。例如,日常的添加、删除、升级和降级的依赖应该使用’go get’来完成。参见 “go help modules “以了解模块功能的概况。
使用方法:
|
|
The commands are:
这些命令是:
download download modules to local cache 下载模块到本地缓存
edit edit go.mod from tools or scripts 从工具或脚本编辑go.mod
graph print module requirement graph
init initialize new module in current directory 在当前目录下初始化新模块
tidy add missing and remove unused modules 添加缺失的模块和删除未使用的模块
vendor make vendored copy of dependencies 制作依赖性的副本
verify verify dependencies have expected content 检验依赖的内容是否符合要求
why explain why packages or modules are needed 解释为什么需要包或模块
Use “go help mod
使用 “go help mod
Download modules to local cache 下载模块到本地缓存
使用方法:
|
|
Download downloads the named modules, which can be module patterns selecting dependencies of the main module or module queries of the form path@version.
下载指定的模块,这些模块可以是选择主模块的依赖关系的模块模式,也可以是path@version形式的模块查询。
With no arguments, download applies to the modules needed to build and test the packages in the main module: the modules explicitly required by the main module if it is at ‘go 1.17’ or higher, or all transitively-required modules if at ‘go 1.16’ or lower.
在没有参数的情况下,下载适用于构建和测试主模块中的包所需的模块:如果主模块是在 “go 1.17 “或更高版本,则是明确需要的模块;如果是在 “go 1.16 “或更低版本,则是所有过渡需要的模块。
The go command will automatically download modules as needed during ordinary execution. The “go mod download” command is useful mainly for pre-filling the local cache or to compute the answers for a Go module proxy.
在普通执行过程中,go命令会根据需要自动下载模块。go mod download “命令主要用于预先填充本地缓存或计算Go模块代理的答案。
By default, download writes nothing to standard output. It may print progress messages and errors to standard error.
默认情况下,下载不会向标准输出写入任何内容。它可以将进度信息和错误打印到标准错误中。
The -json flag causes download to print a sequence of JSON objects to standard output, describing each downloaded module (or failure), corresponding to this Go struct:
-json 标志使 download 将一连串的 JSON 对象打印到标准输出,描述每个下载的模块(或失败),对应于这个 Go 结构:
type Module struct {
Path string // module path
Query string // version query corresponding to this version
Version string // module version
Error string // error loading module
Info string // absolute path to cached .info file
GoMod string // absolute path to cached .mod file
Zip string // absolute path to cached .zip file
Dir string // absolute path to cached source root directory
Sum string // checksum for path, version (as in go.sum)
GoModSum string // checksum for go.mod (as in go.sum)
Origin any // provenance of module
Reuse bool // reuse of old module info is safe
}
The -reuse flag accepts the name of file containing the JSON output of a previous ‘go mod download -json’ invocation. The go command may use this file to determine that a module is unchanged since the previous invocation and avoid redownloading it. Modules that are not redownloaded will be marked in the new output by setting the Reuse field to true. Normally the module cache provides this kind of reuse automatically; the -reuse flag can be useful on systems that do not preserve the module cache.
重用标志接受包含先前 “go mod download -json “调用的JSON输出的文件名。go命令可以使用这个文件来确定一个模块自上一次调用后没有变化,并避免重新下载它。没有被重新下载的模块将在新的输出中通过将Reuse字段设置为true来标记。通常情况下,模块缓存会自动提供这种重用;-reuse标志在不保留模块缓存的系统上可能很有用。
The -x flag causes download to print the commands download executes.
-x标志使download打印download执行的命令。
See https://golang.org/ref/mod#go-mod-download for more about ‘go mod download’.
关于 “go mod download “的更多信息,见https://golang.org/ref/mod#go-mod-download。
See https://golang.org/ref/mod#version-queries for more about version queries.
更多关于版本查询的信息,见https://golang.org/ref/mod#version-queries。
Edit go.mod from tools or scripts 从工具或脚本中编辑go.mod
使用方法:
|
|
Edit provides a command-line interface for editing go.mod, for use primarily by tools or scripts. It reads only go.mod; it does not look up information about the modules involved. By default, edit reads and writes the go.mod file of the main module, but a different target file can be specified after the editing flags.
Edit为编辑go.mod提供了一个命令行接口,主要供工具或脚本使用。它只读取go.mod;不查询相关模块的信息。默认情况下,edit读写主模块的go.mod文件,但可以在编辑标志后指定一个不同的目标文件。
The editing flags specify a sequence of editing operations.
编辑标志指定了一连串的编辑操作。
The -fmt flag reformats the go.mod file without making other changes. This reformatting is also implied by any other modifications that use or rewrite the go.mod file. The only time this flag is needed is if no other flags are specified, as in ‘go mod edit -fmt’.
-fmt标志对go.mod文件进行重新格式化,而不做其他修改。这种重新格式化也被任何其他使用或重写go.mod文件的修改所暗示。唯一需要这个标志的时候是在没有指定其他标志的情况下,如’go mod edit -fmt’。
The -module flag changes the module’s path (the go.mod file’s module line).
-module标志改变模块的路径(go.mod文件的模块行)。
The -require=path@version and -droprequire=path flags add and drop a requirement on the given module path and version. Note that -require overrides any existing requirements on path. These flags are mainly for tools that understand the module graph. Users should prefer ‘go get path@version’ or ‘go get path@none’, which make other go.mod adjustments as needed to satisfy constraints imposed by other modules.
-require=path@version 和 -droprequire=path 标志在给定的模块路径和版本上添加和删除一个需求。注意,-require 覆盖路径上的任何现有需求。这些标志主要用于理解模块图的工具。用户应该更喜欢’go get path@version’或’go get path@none’,它们会根据需要进行其他go.mod调整以满足其他模块的约束。
The -exclude=path@version and -dropexclude=path@version flags add and drop an exclusion for the given module path and version. Note that -exclude=path@version is a no-op if that exclusion already exists.
-exclude=path@version 和 -dropexclude=path@version 标志为给定的模块路径和版本添加和删除一个排除项。注意 -exclude=path@version 是一个无用功,如果该排除法已经存在。
The -replace=old[@v]=new[@v] flag adds a replacement of the given module path and version pair. If the @v in old@v is omitted, a replacement without a version on the left side is added, which applies to all versions of the old module path. If the @v in new@v is omitted, the new path should be a local module root directory, not a module path. Note that -replace overrides any redundant replacements for old[@v], so omitting @v will drop existing replacements for specific versions.
-replace=old[@v]=new[@v] 标志增加了对给定模块路径和版本的替换。如果省略了old@v中的@v,就会添加一个左侧没有版本的替换,它适用于旧模块路径的所有版本。如果new@v中的@v被省略,新路径应该是本地模块根目录,而不是模块路径。注意,-replace 覆盖了old[@v]的任何多余的替换,所以省略@v将放弃特定版本的现有替换。
The -dropreplace=old[@v] flag drops a replacement of the given module path and version pair. If the @v is omitted, a replacement without a version on the left side is dropped.
-dropreplace=old[@v]标志会放弃对给定模块路径和版本的替换。如果省略了@v,左边没有版本的替换会被丢弃。
The -retract=version and -dropretract=version flags add and drop a retraction on the given version. The version may be a single version like “v1.2.3” or a closed interval like “[v1.1.0,v1.1.9]”. Note that -retract=version is a no-op if that retraction already exists.
-retract=version 和 -dropretract=version 标志在给定的版本上添加和删除一个回缩。版本可以是一个单一的版本,如 “v1.2.3 “或一个封闭的区间,如”[v1.1.0,v1.1.9]"。需要注意的是,如果该版本已经存在,那么-retract=version就是一个无用的选项。
The -require, -droprequire, -exclude, -dropexclude, -replace, -dropreplace, -retract, and -dropretract editing flags may be repeated, and the changes are applied in the order given.
-require、-droprequire、-exclude、-dropexclude、-replace、-dropreplace、-retract和-dropretract等编辑标志可以重复使用,并且按照给出的顺序应用这些变化。
The -go=version flag sets the expected Go language version.
-go=version标志设置预期的Go语言版本。
The -print flag prints the final go.mod in its text format instead of writing it back to go.mod.
-print标志以其文本格式打印最终的go.mod,而不是写回go.mod。
The -json flag prints the final go.mod file in JSON format instead of writing it back to go.mod. The JSON output corresponds to these Go types:
-json标志以JSON格式打印最终的go.mod文件,而不是将其写回go.mod。JSON输出对应的是这些Go类型:
|
|
Retract entries representing a single version (not an interval) will have the “Low” and “High” fields set to the same value.
代表单一版本(不是一个区间)的Retract条目将把 “Low “和 “High “字段设置为相同的值。
Note that this only describes the go.mod file itself, not other modules referred to indirectly. For the full set of modules available to a build, use ‘go list -m -json all’.
注意,这只是描述go.mod文件本身,而不是间接引用的其他模块。对于构建中可用的全部模块,使用 “go list -m -json all”。
See https://golang.org/ref/mod#go-mod-edit for more about ‘go mod edit’.
更多关于’go mod edit’的信息请参见https://golang.org/ref/mod#go-mod-edit。
Print module requirement graph 打印模块需求图
使用方法:
|
|
Graph prints the module requirement graph (with replacements applied) in text form. Each line in the output has two space-separated fields: a module and one of its requirements. Each module is identified as a string of the form path@version, except for the main module, which has no @version suffix.
图形以文本形式打印模块需求图(已应用替换)。输出的每一行都有两个空格分隔的区域:一个模块和一个需求。每个模块都被识别为path@version形式的字符串,除了主模块,它没有@version后缀。
The -go flag causes graph to report the module graph as loaded by the given Go version, instead of the version indicated by the ‘go’ directive in the go.mod file.
-go标志使graph报告由指定Go版本加载的模块图,而不是go.mod文件中’go’指令所指示的版本。
See https://golang.org/ref/mod#go-mod-graph for more about ‘go mod graph’.
更多关于’go mod graph’的信息请参见https://golang.org/ref/mod#go-mod-graph。
Initialize new module in current directory 在当前目录下初始化新模块
使用方法:
|
|
Init initializes and writes a new go.mod file in the current directory, in effect creating a new module rooted at the current directory. The go.mod file must not already exist.
Init在当前目录下初始化并写入一个新的go.mod文件,实际上是在当前目录下创建一个新模块。这个go.mod文件必须不存在。
Init accepts one optional argument, the module path for the new module. If the module path argument is omitted, init will attempt to infer the module path using import comments in .go files, vendoring tool configuration files (like Gopkg.lock), and the current directory (if in GOPATH).
Init接受一个可选参数,即新模块的模块路径。如果省略了模块路径参数,init将尝试使用.go文件中的导入注释、销售工具配置文件(如Gopkg.lock)和当前目录(如果在GOPATH中)来推断模块路径。
If a configuration file for a vendoring tool is present, init will attempt to import module requirements from it.
如果卖家工具的配置文件存在,init将尝试从其中导入模块需求。
See https://golang.org/ref/mod#go-mod-init for more about ‘go mod init’.
关于 “go mod init “的更多信息,请参见https://golang.org/ref/mod#go-mod-init。
Add missing and remove unused modules 添加缺失和删除未使用的模块
使用方法:
|
|
Tidy makes sure go.mod matches the source code in the module. It adds any missing modules necessary to build the current module’s packages and dependencies, and it removes unused modules that don’t provide any relevant packages. It also adds any missing entries to go.sum and removes any unnecessary ones.
Tidy确保go.mod与模块中的源代码相匹配。它添加任何缺失的模块来构建当前模块的包和依赖关系,并删除不提供任何相关包的未使用模块。它还在go.sum中添加任何缺少的条目,并删除任何不必要的条目。
The -v flag causes tidy to print information about removed modules to standard error.
-v标志使tidy将删除模块的信息打印到标准错误中。
The -e flag causes tidy to attempt to proceed despite errors encountered while loading packages.
-e标志使tidy尝试继续进行,尽管在加载包时遇到了错误。
The -go flag causes tidy to update the ‘go’ directive in the go.mod file to the given version, which may change which module dependencies are retained as explicit requirements in the go.mod file. (Go versions 1.17 and higher retain more requirements in order to support lazy module loading.)
-go标志使tidy将go.mod文件中的’go’指令更新为给定的版本,这可能会改变哪些模块的依赖性被保留为go.mod文件中的明确要求。(Go 1.17及更高版本保留了更多的需求,以支持懒惰的模块加载)。
The -compat flag preserves any additional checksums needed for the ‘go’ command from the indicated major Go release to successfully load the module graph, and causes tidy to error out if that version of the ‘go’ command would load any imported package from a different module version. By default, tidy acts as if the -compat flag were set to the version prior to the one indicated by the ‘go’ directive in the go.mod file.
-compat 标志保留了任何额外的校验和,以使指定的主要 Go 版本的’go’命令能够成功加载模块图,并且如果该版本的’go’命令将加载任何来自不同模块版本的导入包,则会导致 tidy 出错。默认情况下,tidy的行为就像-compat标志被设置为go.mod文件中’go’指令所指示的版本之前的版本。
See https://golang.org/ref/mod#go-mod-tidy for more about ‘go mod tidy’.
关于 “go mod tidy “的更多信息,见https://golang.org/ref/mod#go-mod-tidy。
Make vendored copy of dependencies 制作依赖关系的卖点拷贝
使用方法:
|
|
Vendor resets the main module’s vendor directory to include all packages needed to build and test all the main module’s packages. It does not include test code for vendored packages.
Vendor重设了主模块的vendor目录,以包括构建和测试所有主模块的包所需的所有包。它不包括卖主包的测试代码。
The -v flag causes vendor to print the names of vendored modules and packages to standard error.
-v标志使Vendor打印出vendored模块和包的名称到标准错误。
The -e flag causes vendor to attempt to proceed despite errors encountered while loading packages.
-e 标志使Vendor在加载包时遇到错误的情况下仍试图继续进行。
The -o flag causes vendor to create the vendor directory at the given path instead of “vendor”. The go command can only use a vendor directory named “vendor” within the module root directory, so this flag is primarily useful for other tools.
o标志使vendor在给定的路径上创建vendor目录而不是 “vendor”。go命令只能在模块根目录下使用名为 “vendor “的厂商目录,所以这个标志主要对其他工具有用。
See https://golang.org/ref/mod#go-mod-vendor for more about ‘go mod vendor’.
关于 “go mod vendor “的更多信息,见https://golang.org/ref/mod#go-mod-vendor。
Verify dependencies have expected content 验证依赖关系是否有预期的内容
使用方法:
|
|
Verify checks that the dependencies of the current module, which are stored in a local downloaded source cache, have not been modified since being downloaded. If all the modules are unmodified, verify prints “all modules verified.” Otherwise it reports which modules have been changed and causes ‘go mod’ to exit with a non-zero status.
Verify检查当前模块的依赖关系,这些依赖关系存储在本地下载的源码缓存中,在下载后没有被修改。如果所有的模块都没有被修改,verify会打印出 “所有模块已验证”。否则,它报告哪些模块被修改了,并使’go mod’以非零状态退出。
See https://golang.org/ref/mod#go-mod-verify for more about ‘go mod verify’.
关于’go mod verify’的更多信息,见https://golang.org/ref/mod#go-mod-verify。
Explain why packages or modules are needed 解释为什么需要包或模块
使用方法:
|
|
Why shows a shortest path in the import graph from the main module to each of the listed packages. If the -m flag is given, why treats the arguments as a list of modules and finds a path to any package in each of the modules.
Why显示了导入图中从主模块到每个列出的包的最短路径。如果给了-m标志,why会把参数当作一个模块列表,并在每个模块中找到通往任何包的路径。
By default, why queries the graph of packages matched by “go list all”, which includes tests for reachable packages. The -vendor flag causes why to exclude tests of dependencies.
默认情况下,why查询由 “go list all “匹配的包图,其中包括对可达包的测试。-vendor标志使why排除了对依赖关系的测试。
The output is a sequence of stanzas, one for each package or module name on the command line, separated by blank lines. Each stanza begins with a comment line “# package” or “# module” giving the target package or module. Subsequent lines give a path through the import graph, one package per line. If the package or module is not referenced from the main module, the stanza will display a single parenthesized note indicating that fact.
输出是一连串的句子,命令行上的每个包或模块名称都有一个句子,用空行隔开。每一节以注释行 “# package “或 “# module “开始,给出目标包或模块。随后的几行给出了导入图的路径,每行一个包。如果该包或模块没有被主模块引用,节段将显示一个括号说明这一事实。
For example:
比如说:
|
|
See https://golang.org/ref/mod#go-mod-why for more about ‘go mod why’.
更多关于 “go mod why “的信息,请参见https://golang.org/ref/mod#go-mod-why。
Workspace maintenance 工作区维护
Work provides access to operations on workspaces.
Work提供了对工作区操作的访问。
Note that support for workspaces is built into many other commands, not just ‘go work’.
请注意,对工作区的支持是内置于许多其他命令中的,而不仅仅是’go work’。
See ‘go help modules’ for information about Go’s module system of which workspaces are a part.
参见 “go help modules “以了解Go的模块系统,工作区是其中的一部分。
See https://go.dev/ref/mod#workspaces for an in-depth reference on workspaces.
参见 https://go.dev/ref/mod#workspaces 以了解关于工作区的深入参考。
See https://go.dev/doc/tutorial/workspaces for an introductory tutorial on workspaces.
参见 https://go.dev/doc/tutorial/workspaces 了解关于工作空间的介绍性教程。
A workspace is specified by a go.work file that specifies a set of module directories with the “use” directive. These modules are used as root modules by the go command for builds and related operations. A workspace that does not specify modules to be used cannot be used to do builds from local modules.
一个工作空间是由go.work文件指定的,该文件用 “use “指令指定了一系列的模块目录。这些模块被go命令作为根模块用于构建和相关操作。没有指定要使用的模块的工作区不能用于从本地模块进行构建。
go.work files are line-oriented. Each line holds a single directive, made up of a keyword followed by arguments. For example:
go.work文件是以行为单位的。每一行都有一个指令,由一个关键词和参数组成。比如说:
go 1.18
use ../foo/bar
use ./baz
replace example.com/foo v1.2.3 => example.com/bar v1.4.5
The leading keyword can be factored out of adjacent lines to create a block, like in Go imports.
领头的关键词可以从相邻的行中派生出来,形成一个块,就像Go导入中一样。
use (
../foo/bar
./baz
)
The use directive specifies a module to be included in the workspace’s set of main modules. The argument to the use directive is the directory containing the module’s go.mod file.
use指令指定一个模块被包含在工作区的主模块集中。use指令的参数是包含该模块的go.mod文件的目录。
The go directive specifies the version of Go the file was written at. It is possible there may be future changes in the semantics of workspaces that could be controlled by this version, but for now the version specified has no effect.
go指令指定了该文件编写的Go版本。未来工作区的语义可能会有变化,可以由这个版本控制,但目前指定的版本没有影响。
The replace directive has the same syntax as the replace directive in a go.mod file and takes precedence over replaces in go.mod files. It is primarily intended to override conflicting replaces in different workspace modules.
替换指令的语法与go.mod文件中的替换指令相同,并优先于go.mod文件中的替换指令。它主要是为了覆盖不同工作区模块中相互冲突的替换。
To determine whether the go command is operating in workspace mode, use the “go env GOWORK” command. This will specify the workspace file being used.
要确定go命令是否在工作区模式下运行,可以使用 “go env GOWORK “命令。这将指定正在使用的工作区文件。
使用方法:
|
|
The commands are:
这些命令是:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
Use “go help work
使用 “go help work
Edit go.work from tools or scripts 从工具或脚本中编辑go.work
使用方法:
|
|
Edit provides a command-line interface for editing go.work, for use primarily by tools or scripts. It only reads go.work; it does not look up information about the modules involved. If no file is specified, Edit looks for a go.work file in the current directory and its parent directories
编辑为编辑go.work提供了一个命令行界面,主要供工具或脚本使用。它只读取go.work,并不查询相关模块的信息。如果没有指定文件,Edit会在当前目录及其父目录中寻找一个go.work文件。
The editing flags specify a sequence of editing operations.
编辑标志指定了一连串的编辑操作。
The -fmt flag reformats the go.work file without making other changes. This reformatting is also implied by any other modifications that use or rewrite the go.mod file. The only time this flag is needed is if no other flags are specified, as in ‘go work edit -fmt’.
-fmt标志对go.work文件进行重新格式化,而不做其他修改。这种重新格式化也被任何其他使用或重写go.mod文件的修改所暗示。唯一需要这个标志的时候是在没有指定其他标志的情况下,如 “go work edit -fmt”。
The -use=path and -dropuse=path flags add and drop a use directive from the go.work file’s set of module directories.
-use=path 和 -dropuse=path 标志从 go.work 文件的模块目录组中添加和删除一个使用指令。
The -replace=old[@v]=new[@v] flag adds a replacement of the given module path and version pair. If the @v in old@v is omitted, a replacement without a version on the left side is added, which applies to all versions of the old module path. If the @v in new@v is omitted, the new path should be a local module root directory, not a module path. Note that -replace overrides any redundant replacements for old[@v], so omitting @v will drop existing replacements for specific versions.
-replace=old[@v]=new[@v] 标志增加了对给定模块路径和版本的替换。如果省略了old@v中的@v,就会添加一个左侧没有版本的替换,这适用于旧模块路径的所有版本。如果new@v中的@v被省略,新路径应该是本地模块根目录,而不是模块路径。注意,-replace 覆盖了old[@v]的任何多余的替换,所以省略@v将放弃特定版本的现有替换。
The -dropreplace=old[@v] flag drops a replacement of the given module path and version pair. If the @v is omitted, a replacement without a version on the left side is dropped.
-dropreplace=old[@v]标志会放弃对给定模块路径和版本的替换。如果省略了@v,左边没有版本的替换会被丢弃。
The -use, -dropuse, -replace, and -dropreplace, editing flags may be repeated, and the changes are applied in the order given.
-use, -dropuse, -replace, 和 -dropreplace, 编辑标志可以重复使用,并且按照给定的顺序应用这些变化。
The -go=version flag sets the expected Go language version.
-go=version 标志设置预期的 Go 语言版本。
The -print flag prints the final go.work in its text format instead of writing it back to go.mod.
-print标志以其文本格式打印最终的go.work,而不是写回go.mod。
The -json flag prints the final go.work file in JSON format instead of writing it back to go.mod. The JSON output corresponds to these Go types:
-json标志以JSON格式打印最终的go.work文件,而不是将其写回go.mod。JSON输出对应的是这些Go类型。
|
|
See the workspaces reference at https://go.dev/ref/mod#workspaces for more information.
更多信息请参见工作区参考,网址:https://go.dev/ref/mod#workspaces。
Initialize workspace file 初始化工作区文件
使用方法:
|
|
Init initializes and writes a new go.work file in the current directory, in effect creating a new workspace at the current directory.
Init在当前目录下初始化并写入一个新的go.work文件,实际上是在当前目录下创建一个新的工作空间。
go work init optionally accepts paths to the workspace modules as arguments. If the argument is omitted, an empty workspace with no modules will be created.
go work init可以选择接受工作区模块的路径作为参数。如果省略该参数,将创建一个没有模块的空工作区。
Each argument path is added to a use directive in the go.work file. The current go version will also be listed in the go.work file.
每个参数路径都被添加到go.work文件中的一个使用指令中。当前的go版本也将被列在go.work文件中。
See the workspaces reference at https://go.dev/ref/mod#workspaces for more information.
更多信息请参见工作空间参考,网址为https://go.dev/ref/mod#workspaces。
Sync workspace build list to modules 同步工作空间构建列表到模块
使用方法:
|
|
Sync syncs the workspace’s build list back to the workspace’s modules
同步将工作区的构建列表同步到工作区的模块中。
The workspace’s build list is the set of versions of all the (transitive) dependency modules used to do builds in the workspace. go work sync generates that build list using the Minimal Version Selection algorithm, and then syncs those versions back to each of modules specified in the workspace (with use directives).
工作区的构建列表是用于在工作区中进行构建的所有(横向)依赖模块的版本集合。go work sync使用最小版本选择算法生成该构建列表,然后将这些版本同步回工作区中指定的每个模块(使用指令)。
The syncing is done by sequentially upgrading each of the dependency modules specified in a workspace module to the version in the build list if the dependency module’s version is not already the same as the build list’s version. Note that Minimal Version Selection guarantees that the build list’s version of each module is always the same or higher than that in each workspace module.
如果依赖模块的版本与构建列表中的版本不一致,则通过将工作区模块中指定的每个依赖模块依次升级到构建列表中的版本来完成同步。请注意,最小版本选择保证构建列表中的每个模块的版本总是与每个工作空间模块中的版本相同或更高。
See the workspaces reference at https://go.dev/ref/mod#workspaces for more information.
更多信息请参见工作区参考资料 https://go.dev/ref/mod#workspaces。
Add modules to workspace file 将模块添加到工作区文件中
使用方法:
|
|
Use provides a command-line interface for adding directories, optionally recursively, to a go.work file.
Use提供了一个命令行接口,用于向go.work文件中添加目录,可以选择递归。
A use directive will be added to the go.work file for each argument directory listed on the command line go.work file, if it exists on disk, or removed from the go.work file if it does not exist on disk.
对于命令行go.work文件中列出的每个参数目录,如果它存在于磁盘上,将在go.work文件中添加一个使用指令,如果它不存在于磁盘上,则从go.work文件中删除。
The -r flag searches recursively for modules in the argument directories, and the use command operates as if each of the directories were specified as arguments: namely, use directives will be added for directories that exist, and removed for directories that do not exist.
-r标志在参数目录中递归地搜索模块,use命令的操作就像每个目录都被指定为参数一样:即,use指令将被添加到存在的目录中,而被删除的目录则不存在。
See the workspaces reference at https://go.dev/ref/mod#workspaces for more information.
更多信息请参见工作空间参考,网址:https://go.dev/ref/mod#workspaces。
Compile and run Go program 编译和运行Go程序
使用方法:
|
|
Run compiles and runs the named main Go package. Typically the package is specified as a list of .go source files from a single directory, but it may also be an import path, file system path, or pattern matching a single known package, as in ‘go run .’ or ‘go run my/cmd’.
运行编译并运行指定的主Go包。通常情况下,包被指定为单个目录下的.go源文件列表,但也可以是导入路径、文件系统路径或匹配单个已知包的模式,如’go run .‘或’go run my/cmd’中。
If the package argument has a version suffix (like @latest or @v1.0.0), “go run” builds the program in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for running programs without affecting the dependencies of the main module.
如果包参数有一个版本后缀(如@latest或@v1.0.0),“go run “将以模块感知模式构建程序,忽略当前目录或任何父目录中的go.mod文件,如果有的话。这对于运行程序而不影响主模块的依赖性很有用。
If the package argument doesn’t have a version suffix, “go run” may run in module-aware mode or GOPATH mode, depending on the GO111MODULE environment variable and the presence of a go.mod file. See ‘go help modules’ for details. If module-aware mode is enabled, “go run” runs in the context of the main module.
如果包参数没有版本后缀,“go run “可能以模块感知模式或GOPATH模式运行,这取决于GO111MODULE环境变量和go.mod文件的存在。详见 “go help modules”。如果启用了模块感知模式,“go run “将在主模块的上下文中运行。
By default, ‘go run’ runs the compiled binary directly: ‘a.out arguments…’. If the -exec flag is given, ‘go run’ invokes the binary using xprog:
默认情况下,“go run “直接运行编译后的二进制文件。‘a.out arguments…’。如果给了-exec标志,“go run “会使用xprog调用二进制文件:
'xprog a.out arguments...'.
If the -exec flag is not given, GOOS or GOARCH is different from the system default, and a program named go_$GOOS_$GOARCH_exec can be found on the current search path, ‘go run’ invokes the binary using that program, for example ‘go_js_wasm_exec a.out arguments…’. This allows execution of cross-compiled programs when a simulator or other execution method is available.
如果没有给出-exec标志,GOOS或GOARCH与系统默认值不同,并且在当前搜索路径上可以找到一个名为go_$GOOS_$GOARCH_exec的程序,‘go run’使用该程序调用二进制文件,例如’go_js_wasm_exec a.out arguments…’。这允许在有模拟器或其他执行方法的情况下执行交叉编译的程序。
By default, ‘go run’ compiles the binary without generating the information used by debuggers, to reduce build time. To include debugger information in the binary, use ‘go build’.
默认情况下,‘go run’编译二进制文件时不产生调试器使用的信息,以减少构建时间。要在二进制文件中包含调试器信息,请使用’go build’。
The exit status of Run is not the exit status of the compiled binary.
运行的退出状态不是编译后的二进制文件的退出状态。
For more about build flags, see ‘go help build’. For more about specifying packages, see ‘go help packages’.
关于构建标志的更多信息,请参见’go help build’。关于指定包的更多信息,请参见’go help packages’。
See also: go build.
另见:go build。
Test packages
使用方法:
|
|
‘go test’可以自动测试由导入路径命名的包。它以如下格式打印出测试结果的摘要:
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
之后是每个失败包的详细输出。
‘go test’重新编译每个包,以及任何名称与文件模式 “*_test.go“相匹配的文件。这些附加文件可以包含测试函数、基准测试函数、模糊测试和示例函数。更多信息见 “go help testfunc"。列出的每个包都会导致执行单独的测试二进制文件。名称以”_"(包括”_test.go")或”.“开头的文件会被忽略。
声明带有”_test“后缀的包的测试文件将被编译为一个单独的包,然后与主测试二进制文件链接并运行。
go工具将忽略名为 “testdata “的目录,使其可用于保存测试所需的辅助数据。
作为构建测试二进制文件的一部分,go test在包及其测试源文件上运行go vet以识别重大问题。如果go vet发现了任何问题,go test会报告这些问题,并且不运行测试二进制文件。只有默认的go vet检查的高置信度子集被使用。这个子集是:’atomic’, ‘bool’, ‘buildtags’, ‘errorsas’, ‘ifaceassert’, ‘nilfunc’, ‘printf’, 和 ‘stringintconv’。你可以通过 “go doc cmd/vet “查看这些和其他vet测试的文档。要禁用go vet的运行,请使用-vet=off标志。要运行所有检查,请使用-vet=all标志。
所有的测试输出和摘要行都被打印到go命令的标准输出,即使测试将它们打印到自己的标准错误中。(go命令的标准错误保留用于打印构建测试的错误。)。
go test在两种不同的模式下运行:
第一种,称为本地目录模式,发生在调用go test时,没有包参数(例如,"go test“或 “go test -v")。在这种模式下,go test编译在当前目录下找到的包源和测试,然后运行产生的测试二进制文件。在这种模式下,缓存(在下面讨论)被禁用。在包测试完成后,go test会打印一个摘要行,显示测试状态(’ok‘或’FAIL’)、包名称和经过的时间。
第二种,称为包列表模式,发生在go test被调用时,有明确的包参数(例如 “go test math","go test ./...",甚至是 “go test .")。在这种模式下,go test编译并测试命令行上列出的每个包。如果一个包测试通过,go test只打印最后的 “ok“摘要行。如果一个包测试失败,go test会打印出完整的测试输出。如果调用-bench或-v标志,即使是通过的包测试,go test也会打印完整的输出,以便显示所要求的基准测试结果或详细的日志。在所有列出的包的测试结束后,如果有任何包测试失败,go test会打印一个最终的 “FAIL“状态。
仅在包列表模式下,go test会缓存成功的包测试结果,以避免不必要地重复运行测试。当测试结果可以从缓存中恢复时,go test将重新显示之前的输出,而不是再次运行测试二进制。当这种情况发生时,go test会在摘要行中打印’(cached)‘来代替经过的时间。
缓存中的匹配规则是,运行涉及相同的测试二进制文件,并且命令行上的标志完全来自于限制性的 “cacheable(可缓存) “测试标志集,定义为-benchtime、-cpu、-list、-parallel、-run、-short、-timeout、-failfast和-v。如果go test的运行有任何测试或非测试标志在这个集合之外,其结果不会被缓存。要禁用测试缓存,请使用除可缓存标志以外的任何测试标志或参数。明确禁止测试缓存的惯用方法是使用 -count=1。打开包的源根目录(通常是$GOPATH)内的文件或参考环境变量的测试只匹配未来的运行,其中的文件和环境变量没有变化。缓存的测试结果会被视为在任何时候都在执行,所以一个成功的包测试结果会被缓存并重复使用,与-timeout设置无关。
除了构建标志之外,"go test“本身处理的标志有:
-args
将命令行的其余部分(-args之后的所有内容)传递给测试二进制文件,不作解释,不作改动。
因为这个标志会消耗命令行的剩余部分。包列表(如果有的话)必须出现在这个标志之前。
-c
将测试二进制文件编译为 pkg.test,但不运行它
(其中 pkg 是包导入路径的最后一个元素)。
文件名可以用-o标志来改变。
-exec xprog
使用xprog运行测试二进制文件。其行为与'go run'相同。详见'go help run'。
-i
安装测试的依赖包。
不要运行测试。
-i标志已被弃用。已编译包会自动缓存。
-json
将测试输出转换为适合自动处理的JSON。
编码细节见'go doc test2json'。
-o file
将测试的二进制文件编译到指定的文件中。
测试仍然运行(除非指定-c或-i)。
测试二进制文件也接受控制测试执行的标志;这些标志也可以通过’go test’访问。详情见’go help testflag’。
更多关于构建标志的信息,见’go help build’。关于指定包的更多信息,见’go help packages’。
另见:go build,go vet。
Run specified go tool 运行指定的go tool
使用方法:
|
|
Tool runs the go tool command identified by the arguments. With no arguments it prints the list of known tools.
工具运行由参数确定的go工具命令。在没有参数的情况下,它会打印出已知工具的列表。
The -n flag causes tool to print the command that would be executed but not execute it.
-n标志使工具打印将被执行的命令,但不执行它。
For more about each tool command, see ‘go doc cmd/
关于每个工具命令的更多信息,见’go doc cmd/
Print Go version 打印Go版本
使用方法:
|
|
Version prints the build information for Go executables.
版本打印Go可执行文件的构建信息。
Go version reports the Go version used to build each of the named executable files.
Go版本报告用于构建每个指定可执行文件的Go版本。
If no files are named on the command line, go version prints its own version information.
如果在命令行中没有指定文件,go version 会打印自己的版本信息。
If a directory is named, go version walks that directory, recursively, looking for recognized Go binaries and reporting their versions. By default, go version does not report unrecognized files found during a directory scan. The -v flag causes it to report unrecognized files.
如果命名了一个目录,go version 会递归地浏览该目录,寻找公认的 Go 二进制文件并报告其版本。默认情况下,go版本不报告在目录扫描中发现的未识别文件。-v 标志使它报告未被识别的文件。
The -m flag causes go version to print each executable’s embedded module version information, when available. In the output, the module information consists of multiple lines following the version line, each indented by a leading tab character.
-m 标志使 go version 打印每个可执行文件的嵌入式模块版本信息(如果有的话)。在输出中,模块信息由版本行之后的多行组成,每行都有一个领先的制表符缩进。
See also: go doc runtime/debug.BuildInfo.
参见:go doc runtime/debug.BuildInfo。
Report likely mistakes in packages 报告包中可能出现的错误
使用方法:
|
|
Vet runs the Go vet command on the packages named by the import paths.
Vet在由导入路径命名的包上运行Go vet命令。
For more about vet and its flags, see ‘go doc cmd/vet’. For more about specifying packages, see ‘go help packages’. For a list of checkers and their flags, see ‘go tool vet help’. For details of a specific checker such as ‘printf’, see ‘go tool vet help printf’.
关于vet和它的标志的更多信息,见’go doc cmd/vet’。更多关于指定包的信息,请参见’go help packages’。关于检查器和它们的标志的列表,见’go tool vet help’。关于特定检查器的细节,比如 “printf”,见 “go tool vet help printf”。
The -n flag prints commands that would be executed. The -x flag prints commands as they are executed.
-n标志打印将被执行的命令。-x标志在命令被执行时打印出来。
The -vettool=prog flag selects a different analysis tool with alternative or additional checks. For example, the ‘shadow’ analyzer can be built and run using these commands:
-vettool=prog标志选择了一个不同的分析工具,具有替代或额外的检查。例如,“shadow “分析器可以用这些命令来构建和运行:
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
The build flags supported by go vet are those that control package resolution and execution, such as -n, -x, -v, -tags, and -toolexec. For more about these flags, see ‘go help build’.
go vet支持的构建标志是那些控制包解析和执行的标志,如-n、-x、-v、-tags和-toolexec。关于这些标志的更多信息,请参阅 “go help build”。
See also: go fmt, go fix.
另见:go fmt、go fix。
Build constraints 构建约束
A build constraint, also known as a build tag, is a condition under which a file should be included in the package. Build constraints are given by a line comment that begins
构建约束,也被称为构建标签,是一个文件应该包括在包中的条件。构建约束是由一行注释给出的,注释的开头是
//go:build
Constraints may appear in any kind of source file (not just Go), but they must appear near the top of the file, preceded only by blank lines and other line comments. These rules mean that in Go files a build constraint must appear before the package clause.
约束条件可以出现在任何类型的源文件中(不仅仅是Go),但它们必须出现在文件的顶部,前面只能有空行和其他行的注释。这些规则意味着在 Go 文件中,构建约束必须出现在 package 条款之前。
To distinguish build constraints from package documentation, a build constraint should be followed by a blank line.
为了区分构建约束和包文件,构建约束的后面应该有一个空行。
A build constraint comment is evaluated as an expression containing build tags combined by ||, &&, and ! operators and parentheses. Operators have the same meaning as in Go.
构建约束注释被评估为一个表达式,其中包含由||、&&、!等操作符和圆括号组成的构建标记。操作符的含义与Go中相同。
For example, the following build constraint constrains a file to build when the “linux” and “386” constraints are satisfied, or when “darwin” is satisfied and “cgo” is not:
例如,下面的构建约束在满足 “linux “和 “386 “约束时,或者在满足 “darwin “而不满足 “cgo “时,约束一个文件的构建:
//go:build (linux && 386) || (darwin && !cgo)
It is an error for a file to have more than one //go:build line.
如果一个文件有多于一个//go:build行,那是一个错误。
During a particular build, the following build tags are satisfied:
在一个特定的构建过程中,要满足以下构建标记:
- the target operating system, as spelled by runtime.GOOS, set with the GOOS environment variable. 目标操作系统,由 runtime.GOOS 拼写,用 GOOS 环境变量设置。
- the target architecture, as spelled by runtime.GOARCH, set with the GOARCH environment variable.目标架构,由 runtime.GOARCH 拼写,用 GOARCH 环境变量设置。
- “unix”, if GOOS is a Unix or Unix-like system.“unix”,如果GOOS是一个Unix或类Unix系统。
- the compiler being used, either “gc” or “gccgo"正在使用的编译器,可以是 “gc “或 “gccgo”
- “cgo”, if the cgo command is supported (see CGO_ENABLED in ‘go help environment’).“cgo”,如果支持cgo命令(见 “go帮助环境 “中的CGO_ENABLED)。
- a term for each Go major release, through the current version: “go1.1” from Go version 1.1 onward, “go1.12” from Go 1.12, and so on.每个Go主要版本的术语,直到当前版本。“go1.1 “代表Go 1.1以后的版本,“go1.12 “代表Go 1.12,以此类推。
- any additional tags given by the -tags flag (see ‘go help build’).任何由 -tags 标志提供的额外标签(见 “go help build”)。
There are no separate build tags for beta or minor releases.
测试版或次要版本没有单独的构建标签。
If a file’s name, after stripping the extension and a possible _test suffix, matches any of the following patterns:
如果一个文件的名字,在去掉扩展名和可能的 _test 后缀后,符合以下任何一种模式:
*_GOOS
*_GOARCH
*_GOOS_GOARCH
(example: source_windows_amd64.go) where GOOS and GOARCH represent any known operating system and architecture values respectively, then the file is considered to have an implicit build constraint requiring those terms (in addition to any explicit constraints in the file).
(例如:source_windows_amd64.go),其中GOOS和GOARCH分别代表任何已知的操作系统和架构值,那么该文件被认为有一个隐含的构建约束,需要这些术语(除了文件中的任何显式约束之外)。
Using GOOS=android matches build tags and files as for GOOS=linux in addition to android tags and files.
使用 GOOS=android 匹配构建标签和文件,就像 GOOS=linux 匹配 android 标签和文件一样。
Using GOOS=illumos matches build tags and files as for GOOS=solaris in addition to illumos tags and files.
使用 GOOS=illumos 与 GOOS=solaris 的构建标签和文件相匹配,此外还有 illumos 标签和文件。
Using GOOS=ios matches build tags and files as for GOOS=darwin in addition to ios tags and files.
使用 GOOS=ios 除了 ios 标签和文件外,还与 GOOS=darwin 的构建标签和文件相匹配。
To keep a file from being considered for the build:
要使一个文件不被考虑在构建中:
//go:build ignore
(any other unsatisfied word will work as well, but “ignore” is conventional.)
(任何其他不满足的词也可以,但 “忽略 “是传统的。)
To build a file only when using cgo, and only on Linux and OS X:
只在使用 cgo 时构建一个文件,而且只在 Linux 和 OS X 上:
//go:build cgo && (linux || darwin)
Such a file is usually paired with another file implementing the default functionality for other systems, which in this case would carry the constraint:
这样的文件通常与另一个实现其他系统默认功能的文件配对,在这种情况下,它将带有约束条件:
//go:build !(cgo && (linux || darwin))
Naming a file dns_windows.go will cause it to be included only when building the package for Windows; similarly, math_386.s will be included only when building the package for 32-bit x86.
将文件命名为dns_windows.go将导致它只在为Windows构建包时被包含;类似地,math_386.s将只在为32位x86构建包时被包含。
Go versions 1.16 and earlier used a different syntax for build constraints, with a “// +build” prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax.
Go 1.16及以前的版本对构建约束使用了不同的语法,前缀为”// +build”。当遇到旧的语法时,gofmt命令会添加一个等价的//go:build约束。
Build modes 构建模式
The ‘go build’ and ‘go install’ commands take a -buildmode argument which indicates which kind of object file is to be built. Currently supported values are:
go build “和 “go install “命令需要一个-buildmode参数,用于指示要构建的对象文件的类型。目前支持的值是:
-buildmode=archive
Build the listed non-main packages into .a files. Packages named
main are ignored.
-buildmode=c-archive
Build the listed main package, plus all packages it imports,
into a C archive file. The only callable symbols will be those
functions exported using a cgo //export comment. Requires
exactly one main package to be listed.
-buildmode=c-shared
Build the listed main package, plus all packages it imports,
into a C shared library. The only callable symbols will
be those functions exported using a cgo //export comment.
Requires exactly one main package to be listed.
-buildmode=default
Listed main packages are built into executables and listed
non-main packages are built into .a files (the default
behavior).
-buildmode=shared
Combine all the listed non-main packages into a single shared
library that will be used when building with the -linkshared
option. Packages named main are ignored.
-buildmode=exe
Build the listed main packages and everything they import into
executables. Packages not named main are ignored.
-buildmode=pie
Build the listed main packages and everything they import into
position independent executables (PIE). Packages not named
main are ignored.
-buildmode=plugin
Build the listed main packages, plus all packages that they
import, into a Go plugin. Packages not named main are ignored.
On AIX, when linking a C program that uses a Go archive built with -buildmode=c-archive, you must pass -Wl,-bnoobjreorder to the C compiler.
在AIX上,当连接使用以-buildmode=c-archive构建的Go存档的C程序时,必须将-Wl,-bnoobjreorder传递给C编译器。
Calling between Go and C 在 Go 和 C 之间的调用
There are two different ways to call between Go and C/C++ code.
有两种不同的方法可以在Go和C/C++代码之间进行调用。
The first is the cgo tool, which is part of the Go distribution. For information on how to use it see the cgo documentation (go doc cmd/cgo).
第一种是cgo工具,它是Go发行版的一部分。关于如何使用它的信息,请参见cgo文档(go doc cmd/cgo)。
The second is the SWIG program, which is a general tool for interfacing between languages. For information on SWIG see http://swig.org/. When running go build, any file with a .swig extension will be passed to SWIG. Any file with a .swigcxx extension will be passed to SWIG with the -c++ option.
第二个是SWIG程序,它是一个用于语言间接口的通用工具。关于SWIG的信息见http://swig.org/。当运行go build时,任何带有.swig扩展名的文件都会被传递给SWIG。任何以.swigcxx为扩展名的文件都将被传递给带有-c++选项的SWIG。
When either cgo or SWIG is used, go build will pass any .c, .m, .s, .S or .sx files to the C compiler, and any .cc, .cpp, .cxx files to the C++ compiler. The CC or CXX environment variables may be set to determine the C or C++ compiler, respectively, to use.
当使用cgo或SWIG时,go build将把任何.c、.m、.s、.S或.sx文件传给C编译器,把任何.cc、.cpp、.cxx文件传给C++编译器。可以设置CC或CXX环境变量来决定分别使用C或C++编译器。
Build and test caching 构建和测试缓存
The go command caches build outputs for reuse in future builds. The default location for cache data is a subdirectory named go-build in the standard user cache directory for the current operating system. Setting the GOCACHE environment variable overrides this default, and running ‘go env GOCACHE’ prints the current cache directory.
go命令对构建输出进行缓存,以便在未来的构建中重复使用。缓存数据的默认位置是当前操作系统的标准用户缓存目录下的一个名为go-build的子目录。设置GOCACHE环境变量可以覆盖这个默认位置,运行 “go env GOCACHE “可以打印出当前的缓存目录。
The go command periodically deletes cached data that has not been used recently. Running ‘go clean -cache’ deletes all cached data.
go命令会定期删除最近没有使用过的缓存数据。运行’go clean -cache’可以删除所有缓存数据。
The build cache correctly accounts for changes to Go source files, compilers, compiler options, and so on: cleaning the cache explicitly should not be necessary in typical use. However, the build cache does not detect changes to C libraries imported with cgo. If you have made changes to the C libraries on your system, you will need to clean the cache explicitly or else use the -a build flag (see ‘go help build’) to force rebuilding of packages that depend on the updated C libraries.
构建缓存可以正确地说明 Go 源文件、编译器、编译器选项等的变化:在通常的使用中,应该没有必要明确地清理缓存。然而,构建缓存并不能检测到用 cgo 导入的 C 库的变化。如果你对系统中的C库进行了修改,你将需要明确地清理缓存,或者使用-a build标志(见 “go help build”)来强制重建依赖于更新的C库的包。
The go command also caches successful package test results. See ‘go help test’ for details. Running ‘go clean -testcache’ removes all cached test results (but not cached build results).
go命令也会缓存成功的包测试结果。详情见’go help test’。运行’go clean -testcache’可以删除所有缓存的测试结果(但不包括缓存的构建结果)。
The go command also caches values used in fuzzing with ‘go test -fuzz’, specifically, values that expanded code coverage when passed to a fuzz function. These values are not used for regular building and testing, but they’re stored in a subdirectory of the build cache. Running ‘go clean -fuzzcache’ removes all cached fuzzing values. This may make fuzzing less effective, temporarily.
go命令还缓存了用于’go test -fuzz’的模糊测试的值,特别是传递给模糊测试函数时扩大代码覆盖率的值。这些值不用于常规的构建和测试,但它们被存储在构建缓存的一个子目录中。运行 “go clean -fuzzcache “可以删除所有缓存的模糊值。这可能使模糊测试暂时不那么有效。
The GODEBUG environment variable can enable printing of debugging information about the state of the cache:
GODEBUG环境变量可以启用打印关于缓存状态的调试信息:
GODEBUG=gocacheverify=1 causes the go command to bypass the use of any cache entries and instead rebuild everything and check that the results match existing cache entries.
GODEBUG=gocacheverify=1 导致go命令绕过使用任何缓存条目,而是重建一切,并检查结果是否与现有的缓存条目相符。
GODEBUG=gocachehash=1 causes the go command to print the inputs for all of the content hashes it uses to construct cache lookup keys. The output is voluminous but can be useful for debugging the cache.
GODEBUG=gocachehash=1使go命令打印所有用于构建缓存查找键的内容哈希值的输入。输出量很大,但对调试缓存很有用。
GODEBUG=gocachetest=1 causes the go command to print details of its decisions about whether to reuse a cached test result.
GODEBUG=gocachetest=1 会使go命令打印关于是否重复使用缓存测试结果的决定细节。
Environment variables 环境变量
The go command and the tools it invokes consult environment variables for configuration. If an environment variable is unset, the go command uses a sensible default setting. To see the effective setting of the variable
go命令和它调用的工具会参考环境变量进行配置。如果一个环境变量没有设置,go命令会使用一个合理的默认设置。要查看变量
General-purpose environment variables:
通用的环境变量:
GO111MODULE
Controls whether the go command runs in module-aware mode or GOPATH mode.
May be "off", "on", or "auto".
See https://golang.org/ref/mod#mod-commands.
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
information for reuse in future builds.
GOMODCACHE
The directory where the go command will store downloaded modules.
GODEBUG
Enable various debugging facilities. See 'go doc runtime'
for details.
GOENV
The location of the Go environment configuration file.
Cannot be set using 'go env -w'.
Setting GOENV=off in the environment disables the use of the
default configuration file.
GOFLAGS
A space-separated list of -flag=value settings to apply
to go commands by default, when the given flag is known by
the current command. Each entry must be a standalone flag.
Because the entries are space-separated, flag values must
not contain spaces. Flags listed on the command line
are applied after this list and therefore override it.
GOINSECURE
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
of module path prefixes that should always be fetched in an insecure
manner. Only applies to dependencies that are being fetched directly.
GOINSECURE does not disable checksum database validation. GOPRIVATE or
GONOSUMDB may be used to achieve that.
GOOS
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
GOPATH
For more details see: 'go help gopath'.
GOPROXY
URL of Go module proxy. See https://golang.org/ref/mod#environment-variables
and https://golang.org/ref/mod#module-proxy for details.
GOPRIVATE, GONOPROXY, GONOSUMDB
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
of module path prefixes that should always be fetched directly
or that should not be compared against the checksum database.
See https://golang.org/ref/mod#private-modules.
GOROOT
The root of the go tree.
GOSUMDB
The name of checksum database to use and optionally its public key and
URL. See https://golang.org/ref/mod#authenticating.
GOTMPDIR
The directory where the go command will write
temporary source files, packages, and binaries.
GOVCS
Lists version control commands that may be used with matching servers.
See 'go help vcs'.
GOWORK
In module aware mode, use the given go.work file as a workspace file.
By default or when GOWORK is "auto", the go command searches for a
file named go.work in the current directory and then containing directories
until one is found. If a valid go.work file is found, the modules
specified will collectively be used as the main modules. If GOWORK
is "off", or a go.work file is not found in "auto" mode, workspace
mode is disabled.
Environment variables for use with cgo:
与cgo一起使用的环境变量:
AR
The command to use to manipulate library archives when
building with the gccgo compiler.
The default is 'ar'.
CC
The command to use to compile C code.
CGO_ENABLED
Whether the cgo command is supported. Either 0 or 1.
CGO_CFLAGS
Flags that cgo will pass to the compiler when compiling
C code.
CGO_CFLAGS_ALLOW
A regular expression specifying additional flags to allow
to appear in #cgo CFLAGS source code directives.
Does not apply to the CGO_CFLAGS environment variable.
CGO_CFLAGS_DISALLOW
A regular expression specifying flags that must be disallowed
from appearing in #cgo CFLAGS source code directives.
Does not apply to the CGO_CFLAGS environment variable.
CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
but for the C preprocessor.
CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
but for the C++ compiler.
CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
but for the Fortran compiler.
CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
but for the linker.
CXX
The command to use to compile C++ code.
FC
The command to use to compile Fortran code.
PKG_CONFIG
Path to pkg-config tool.
Architecture-specific environment variables:
架构特定的环境变量:
GOARM
For GOARCH=arm, the ARM architecture for which to compile.
Valid values are 5, 6, 7.
GO386
For GOARCH=386, how to implement floating point instructions.
Valid values are sse2 (default), softfloat.
GOAMD64
For GOARCH=amd64, the microarchitecture level for which to compile.
Valid values are v1 (default), v2, v3, v4.
See https://golang.org/wiki/MinimumRequirements#amd64
GOMIPS
For GOARCH=mips{,le}, whether to use floating point instructions.
Valid values are hardfloat (default), softfloat.
GOMIPS64
For GOARCH=mips64{,le}, whether to use floating point instructions.
Valid values are hardfloat (default), softfloat.
GOPPC64
For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
Valid values are power8 (default), power9.
GOWASM
For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
Valid values are satconv, signext.
Special-purpose environment variables:
特殊用途的环境变量:
GCCGOTOOLDIR
If set, where to find gccgo tools, such as cgo.
The default is based on how gccgo was configured.
GOEXPERIMENT
Comma-separated list of toolchain experiments to enable or disable.
The list of available experiments may change arbitrarily over time.
See src/internal/goexperiment/flags.go for currently valid values.
Warning: This variable is provided for the development and testing
of the Go toolchain itself. Use beyond that purpose is unsupported.
GOROOT_FINAL
The root of the installed Go tree, when it is
installed in a location other than where it is built.
File names in stack traces are rewritten from GOROOT to
GOROOT_FINAL.
GO_EXTLINK_ENABLED
Whether the linker should use external linking mode
when using -linkmode=auto with code that uses cgo.
Set to 0 to disable external linking mode, 1 to enable it.
GIT_ALLOW_PROTOCOL
Defined by Git. A colon-separated list of schemes that are allowed
to be used with git fetch/clone. If set, any scheme not explicitly
mentioned will be considered insecure by 'go get'.
Because the variable is defined by Git, the default value cannot
be set using 'go env -w'.
Additional information available from ‘go env’ but not read from the environment:
从’go env’可以获得额外的信息,但不能从环境中读取:
GOEXE
The executable file name suffix (".exe" on Windows, "" on other systems).
GOGCCFLAGS
A space-separated list of arguments supplied to the CC command.
GOHOSTARCH
The architecture (GOARCH) of the Go toolchain binaries.
GOHOSTOS
The operating system (GOOS) of the Go toolchain binaries.
GOMOD
The absolute path to the go.mod of the main module.
If module-aware mode is enabled, but there is no go.mod, GOMOD will be
os.DevNull ("/dev/null" on Unix-like systems, "NUL" on Windows).
If module-aware mode is disabled, GOMOD will be the empty string.
GOTOOLDIR
The directory where the go tools (compile, cover, doc, etc...) are installed.
GOVERSION
The version of the installed Go tree, as reported by runtime.Version.
File types 文件类型
The go command examines the contents of a restricted set of files in each directory. It identifies which files to examine based on the extension of the file name. These extensions are:
go 命令检查每个目录中受限制的文件集的内容。它根据文件名的扩展名来确定要检查的文件。这些扩展名是:
.go
Go source files.
.c, .h
C source files.
If the package uses cgo or SWIG, these will be compiled with the
OS-native compiler (typically gcc); otherwise they will
trigger an error.
.cc, .cpp, .cxx, .hh, .hpp, .hxx
C++ source files. Only useful with cgo or SWIG, and always
compiled with the OS-native compiler.
.m
Objective-C source files. Only useful with cgo, and always
compiled with the OS-native compiler.
.s, .S, .sx
Assembler source files.
If the package uses cgo or SWIG, these will be assembled with the
OS-native assembler (typically gcc (sic)); otherwise they
will be assembled with the Go assembler.
.swig, .swigcxx
SWIG definition files.
.syso
System object files.
Files of each of these types except .syso may contain build constraints, but the go command stops scanning for build constraints at the first item in the file that is not a blank line or //-style line comment. See the go/build package documentation for more details.
除.syso外,上述每种类型的文件都可能包含构建约束,但go命令会在文件中第一项不是空行或//式行注释时停止扫描构建约束。更多细节请参见go/build包文档。
The go.mod file go.mod文件
A module version is defined by a tree of source files, with a go.mod file in its root. When the go command is run, it looks in the current directory and then successive parent directories to find the go.mod marking the root of the main (current) module.
一个模块版本由一棵源文件树定义,其根部有一个go.mod文件。当go命令运行时,它会在当前目录中寻找,然后在连续的父目录中寻找标记主(当前)模块根部的go.mod。
The go.mod file format is described in detail at https://golang.org/ref/mod#go-mod-file.
go.mod文件格式的详细描述见https://golang.org/ref/mod#go-mod-file。
To create a new go.mod file, use ‘go mod init’. For details see ‘go help mod init’ or https://golang.org/ref/mod#go-mod-init.
要创建一个新的go.mod文件,使用’go mod init’。详情见’go help mod init’或https://golang.org/ref/mod#go-mod-init。
To add missing module requirements or remove unneeded requirements, use ‘go mod tidy’. For details, see ‘go help mod tidy’ or https://golang.org/ref/mod#go-mod-tidy.
要添加缺失的模块需求或删除不需要的需求,使用’go mod tidy’。详情请见’go help mod tidy’或https://golang.org/ref/mod#go-mod-tidy。
To add, upgrade, downgrade, or remove a specific module requirement, use ‘go get’. For details, see ‘go help module-get’ or https://golang.org/ref/mod#go-get.
要添加,升级,降级,或删除一个特定的模块需求,使用’go get’。详情请见’go help module-get’或https://golang.org/ref/mod#go-get。
To make other changes or to parse go.mod as JSON for use by other tools, use ‘go mod edit’. See ‘go help mod edit’ or https://golang.org/ref/mod#go-mod-edit.
要进行其他修改或将go.mod解析为JSON格式供其他工具使用,使用’go mod edit’。参见’go help mod edit’或https://golang.org/ref/mod#go-mod-edit。
GOPATH environment variable GOPATH环境变量
The Go path is used to resolve import statements. It is implemented by and documented in the go/build package.
Go路径用于解决导入语句。它由go/build包实现并记录在案。
The GOPATH environment variable lists places to look for Go code. On Unix, the value is a colon-separated string. On Windows, the value is a semicolon-separated string. On Plan 9, the value is a list.
GOPATH 环境变量列出了寻找 Go 代码的地方。在 Unix 上,该值是一个用冒号分隔的字符串。在Windows上,该值是一个分号分隔的字符串。在 Plan 9 上,该值是一个列表。
If the environment variable is unset, GOPATH defaults to a subdirectory named “go” in the user’s home directory ($HOME/go on Unix, %USERPROFILE%\go on Windows), unless that directory holds a Go distribution. Run “go env GOPATH” to see the current GOPATH.
如果环境变量没有设置,GOPATH默认为用户主目录中名为 “go “的子目录(Unix中为$HOME/go,Windows中为%USERPROFILE%\go),除非该目录中有Go发行版。运行 “go env GOPATH “可以看到当前的 GOPATH。
See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
参见 https://golang.org/wiki/SettingGOPATH 来设置一个自定义的 GOPATH。
Each directory listed in GOPATH must have a prescribed structure:
GOPATH 中列出的每个目录必须有规定的结构:
The src directory holds source code. The path below src determines the import path or executable name.
src目录存放源代码。src下面的路径决定了导入路径或可执行文件名。
The pkg directory holds installed package objects. As in the Go tree, each target operating system and architecture pair has its own subdirectory of pkg (pkg/GOOS_GOARCH).
pkg目录存放已安装的包对象。和Go树一样,每个目标操作系统和架构对都有自己的pkg子目录(pkg/GOOS_GOARCH)。
If DIR is a directory listed in the GOPATH, a package with source in DIR/src/foo/bar can be imported as “foo/bar” and has its compiled form installed to “DIR/pkg/GOOS_GOARCH/foo/bar.a”.
如果DIR是GOPATH中列出的目录,一个源码在DIR/src/foo/bar的包可以被导入为 “foo/bar”,并将其编译后的形式安装到 “DIR/pkg/GOOS_GOARCH/foo/bar.a”。
The bin directory holds compiled commands. Each command is named for its source directory, but only the final element, not the entire path. That is, the command with source in DIR/src/foo/quux is installed into DIR/bin/quux, not DIR/bin/foo/quux. The “foo/” prefix is stripped so that you can add DIR/bin to your PATH to get at the installed commands. If the GOBIN environment variable is set, commands are installed to the directory it names instead of DIR/bin. GOBIN must be an absolute path.
bin目录存放编译后的命令。每条命令都以其源目录命名,但只是最后的元素,而不是整个路径。也就是说,源码在DIR/src/foo/quux的命令被安装到DIR/bin/quux,而不是DIR/bin/foo/quux。foo/“前缀被去掉了,这样你就可以在PATH中加入DIR/bin来获取已安装的命令。如果设置了GOBIN环境变量,命令会被安装到它命名的目录中,而不是DIR/bin。GOBIN必须是一个绝对路径。
Here’s an example directory layout:
下面是一个目录布局的例子:
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
Go searches each directory listed in GOPATH to find source code, but new packages are always downloaded into the first directory in the list.
Go会搜索GOPATH中列出的每个目录来寻找源代码,但新的包总是被下载到列表中的第一个目录。
See https://golang.org/doc/code.html for an example.
请参阅 https://golang.org/doc/code.html 以了解一个例子。
GOPATH and Modules GOPATH 和模块
When using modules, GOPATH is no longer used for resolving imports. However, it is still used to store downloaded source code (in GOPATH/pkg/mod) and compiled commands (in GOPATH/bin).
当使用模块时,GOPATH 不再用于解决导入问题。然而,它仍然被用来存储下载的源代码(在GOPATH/pkg/mod)和编译的命令(在GOPATH/bin)。
Internal Directories 内部目录
Code in or below a directory named “internal” is importable only by code in the directory tree rooted at the parent of “internal”. Here’s an extended version of the directory layout above:
在名为 “内部 “的目录中或其下的代码只能被根植于 “内部 “的父目录树中的代码所导入。下面是上述目录布局的一个扩展版本:
/home/user/go/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
internal/
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The code in z.go is imported as “foo/internal/baz”, but that import statement can only appear in source files in the subtree rooted at foo. The source files foo/f.go, foo/bar/x.go, and foo/quux/y.go can all import “foo/internal/baz”, but the source file crash/bang/b.go cannot.
z.go中的代码被导入为 “foo/internal/baz”,但该导入语句只能出现在以foo为根的子树上的源文件中。源文件foo/f.go、foo/bar/x.go和foo/quux/y.go都可以导入 “foo/internal/baz”,但源文件crash/bang/b.go不能。
See https://golang.org/s/go14internal for details.
详见https://golang.org/s/go14internal。
Vendor Directories - Vendor目录
Go 1.6 includes support for using local copies of external dependencies to satisfy imports of those dependencies, often referred to as vendoring.
Go 1.6包括支持使用外部依赖的本地副本来满足对这些依赖的导入,通常被称为vendoring。
Code below a directory named “vendor” is importable only by code in the directory tree rooted at the parent of “vendor”, and only using an import path that omits the prefix up to and including the vendor element.
在名为 “vendor “的目录下的代码只能被根植于 “vendor “的父目录树中的代码导入,并且只能使用省略前缀的导入路径,直到并包括vendor元素。
Here’s the example from the previous section, but with the “internal” directory renamed to “vendor” and a new foo/vendor/crash/bang directory added:
下面是上一节的例子,但 “内部 “目录重命名为 “vendor”,并添加了一个新的foo/vendor/crash/bang目录:
/home/user/go/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
vendor/
crash/
bang/ (go code in package bang)
b.go
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.go
The same visibility rules apply as for internal, but the code in z.go is imported as “baz”, not as “foo/vendor/baz”.
同样的可见性规则适用于内部,但z.go中的代码被导入为 “baz”,而不是 “foo/vendor/baz”。
Code in vendor directories deeper in the source tree shadows code in higher directories. Within the subtree rooted at foo, an import of “crash/bang” resolves to “foo/vendor/crash/bang”, not the top-level “crash/bang”.
源代码树中较深的供应商目录中的代码会对较高目录中的代码产生阴影。在以foo为根的子树中,“crash/bang “的导入被解析为 “foo/vendor/crash/bang”,而不是顶级的 “crash/bang”。
Code in vendor directories is not subject to import path checking (see ‘go help importpath’).
供应商目录中的代码不受导入路径检查的影响(参见 “go help importpath”)。
When ‘go get’ checks out or updates a git repository, it now also updates submodules.
当’go get’检出或更新 git 仓库时,它现在也会更新子模块。
Vendor directories do not affect the placement of new repositories being checked out for the first time by ‘go get’: those are always placed in the main GOPATH, never in a vendor subtree.
供应商目录不会影响’go get’首次签出的新仓库的位置:这些仓库总是被放在主GOPATH中,而不是供应商子树中。
See https://golang.org/s/go15vendor for details.
详见https://golang.org/s/go15vendor。
Legacy GOPATH go get 传统的GOPATH go get
The ‘go get’ command changes behavior depending on whether the go command is running in module-aware mode or legacy GOPATH mode. This help text, accessible as ‘go help gopath-get’ even in module-aware mode, describes ‘go get’ as it operates in legacy GOPATH mode.
go get “命令的行为变化取决于go命令是在模块感知模式还是传统的GOPATH模式下运行。这个帮助文本,即使在模块感知模式下也可以通过 “go help gopath-get “访问,描述了 “go get “在传统GOPATH模式下的操作。
使用方法: go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]
Get downloads the packages named by the import paths, along with their dependencies. It then installs the named packages, like ‘go install’.
get下载由导入路径命名的包,以及它们的依赖关系。然后它安装这些命名的包,就像 “go install”:
The -d flag instructs get to stop after downloading the packages; that is, it instructs get not to install the packages.
-d 标志指示 get 在下载包后停止;也就是说,它指示 get 不要安装这些包。
The -f flag, valid only when -u is set, forces get -u not to verify that each package has been checked out from the source control repository implied by its import path. This can be useful if the source is a local fork of the original.
-f 标志,只有在设置了 -u 时才有效,它迫使 get -u 不去验证每个包是否已经从其导入路径所暗示的源控制库中签出。如果源文件是原始文件的本地分叉,这可能很有用。
The -fix flag instructs get to run the fix tool on the downloaded packages before resolving dependencies or building the code.
-fix 标志指示 get 在解决依赖关系或构建代码之前对下载的包运行修复工具。
The -t flag instructs get to also download the packages required to build the tests for the specified packages.
-t 标志指示 get 也下载为指定包构建测试所需的包。
The -u flag instructs get to use the network to update the named packages and their dependencies. By default, get uses the network to check out missing packages but does not use it to look for updates to existing packages.
u标志指示get使用网络来更新指定的包和它们的依赖关系。默认情况下,get 使用网络来检查缺失的包,但不使用它来寻找现有包的更新。
The -v flag enables verbose progress and debug output.
-v 标志可以使进度和调试输出更加详细。
Get also accepts build flags to control the installation. See ‘go help build’.
Get也接受构建标志来控制安装。参见 “go help build”:
When checking out a new package, get creates the target directory GOPATH/src/
当检查一个新的包时,get会创建目标目录GOPATH/src/
When checking out or updating a package, get looks for a branch or tag that matches the locally installed version of Go. The most important rule is that if the local installation is running version “go1”, get searches for a branch or tag named “go1”. If no such version exists it retrieves the default branch of the package.
当签出或更新包时,get 会寻找与本地安装的 Go 版本相匹配的分支或标签。最重要的规则是,如果本地安装的版本是 “go1”,get 会搜索名为 “go1 “的分支或标签。如果没有这样的版本,它会检索包的默认分支。
When go get checks out or updates a Git repository, it also updates any git submodules referenced by the repository.
当 go get 签出或更新一个 Git 仓库时,它也会更新该仓库所引用的任何 git 子模块。
Get never checks out or updates code stored in vendor directories.
Get不会检出或更新存储在供应商目录中的代码。
For more about specifying packages, see ‘go help packages’.
关于指定包的更多信息,请参见 “go help packages”。
For more about how ‘go get’ finds source code to download, see ‘go help importpath’.
更多关于’go get’如何找到要下载的源代码,见’go help importpath’。
This text describes the behavior of get when using GOPATH to manage source code and dependencies. If instead the go command is running in module-aware mode, the details of get’s flags and effects change, as does ‘go help get’. See ‘go help modules’ and ‘go help module-get’.
这段文字描述了使用GOPATH来管理源代码和依赖关系时get的行为。如果go命令是在模块感知模式下运行,get的标志和效果的细节就会改变,‘go help get’也是如此。参见 “go help modules “和 “go help module-get”。
See also: go build, go install, go clean.
另见:go build,go install,go clean。
Module proxy protocol 模块代理协议
A Go module proxy is any web server that can respond to GET requests for URLs of a specified form. The requests have no query parameters, so even a site serving from a fixed file system (including a file:/// URL) can be a module proxy.
Go模块代理是任何能够响应指定形式的URL的GET请求的网络服务器。这些请求没有查询参数,所以即使是一个从固定文件系统(包括file:/// URL)提供服务的网站也可以是一个模块代理。
For details on the GOPROXY protocol, see https://golang.org/ref/mod#goproxy-protocol.
关于GOPROXY协议的细节,见https://golang.org/ref/mod#goproxy-protocol。
Import path syntax 导入路径语法
An import path (see ‘go help packages’) denotes a package stored in the local file system. In general, an import path denotes either a standard package (such as “unicode/utf8”) or a package found in one of the work spaces (For more details see: ‘go help gopath’).
一个导入路径(见 “go help packages”)表示一个存储在本地文件系统中的包。一般来说,导入路径表示一个标准包(如 “unicode/utf8”)或一个在工作空间中发现的包(更多细节见:“go help gopath”)。
Relative import paths 相对的导入路径
An import path beginning with ./ or ../ is called a relative path. The toolchain supports relative import paths as a shortcut in two ways.
一个以./或./开头的导入路径被称为相对路径。工具链以两种方式支持相对导入路径作为一种快捷方式。
First, a relative path can be used as a shorthand on the command line. If you are working in the directory containing the code imported as “unicode” and want to run the tests for “unicode/utf8”, you can type “go test ./utf8” instead of needing to specify the full path. Similarly, in the reverse situation, “go test ..” will test “unicode” from the “unicode/utf8” directory. Relative patterns are also allowed, like “go test ./…” to test all subdirectories. See ‘go help packages’ for details on the pattern syntax.
首先,相对路径可以作为命令行上的速记方式。如果你在包含作为 “unicode “导入的代码的目录中工作,并想运行 “unicode/utf8 “的测试,你可以输入 “go test ./utf8”,而不需要指定全路径。同样,在相反的情况下,“go test … “将测试 “unicode/utf8 “目录下的 “unicode”。相对模式也是允许的,比如 “go test ./… “可以测试所有子目录。关于模式语法的细节,请参见 “go help packages”。
Second, if you are compiling a Go program not in a work space, you can use a relative path in an import statement in that program to refer to nearby code also not in a work space. This makes it easy to experiment with small multipackage programs outside of the usual work spaces, but such programs cannot be installed with “go install” (there is no work space in which to install them), so they are rebuilt from scratch each time they are built. To avoid ambiguity, Go programs cannot use relative import paths within a work space.
其次,如果你正在编译一个不在工作空间的Go程序,你可以在该程序的导入语句中使用相对路径来引用附近也不在工作空间的代码。这使得在通常的工作空间之外试验小型多包程序变得很容易,但这样的程序不能用 “go install “来安装(没有工作空间可以安装它们),所以每次构建它们时都要从头开始重建。为了避免歧义,Go程序不能在工作空间内使用相对导入路径。
Remote import paths 远程导入路径
Certain import paths also describe how to obtain the source code for the package using a revision control system.
某些导入路径还描述了如何使用修订控制系统获得包的源代码。
A few common code hosting sites have special syntax:
一些常见的代码托管网站有特殊的语法:
Bitbucket (Git, Mercurial)
import "bitbucket.org/user/project"
import "bitbucket.org/user/project/sub/directory"
GitHub (Git)
import "github.com/user/project"
import "github.com/user/project/sub/directory"
Launchpad (Bazaar)
import "launchpad.net/project"
import "launchpad.net/project/series"
import "launchpad.net/project/series/sub/directory"
import "launchpad.net/~user/project/branch"
import "launchpad.net/~user/project/branch/sub/directory"
IBM DevOps Services (Git)
import "hub.jazz.net/git/user/project"
import "hub.jazz.net/git/user/project/sub/directory"
For code hosted on other servers, import paths may either be qualified with the version control type, or the go tool can dynamically fetch the import path over https/http and discover where the code resides from a tag in the HTML.
对于托管在其他服务器上的代码,导入路径可以用版本控制类型来限定,或者go工具可以通过https/http动态获取导入路径,并从HTML中的标签发现代码的位置。
To declare the code location, an import path of the form
为了声明代码的位置,一个导入路径的形式为
repository.vcs/path
specifies the given repository, with or without the .vcs suffix, using the named version control system, and then the path inside that repository. The supported version control systems are:
的形式指定给定的版本库,无论是否带有 .vcs 后缀,使用指定的版本控制系统,然后是该版本库内的路径。支持的版本控制系统有:
Bazaar .bzr
Fossil .fossil
Git .git
Mercurial .hg
Subversion .svn
For example,
比如说,
|
|
denotes the root directory of the Mercurial repository at example.org/user/foo or foo.hg, and
表示位于example.org/user/foo或foo.hg的Mercurial仓库的根目录,而
|
|
denotes the foo/bar directory of the Git repository at example.org/repo or repo.git.
表示位于 example.org/repo 或 repo.git 的 Git 仓库的 foo/bar 目录。
When a version control system supports multiple protocols, each is tried in turn when downloading. For example, a Git download tries https://, then git+ssh://.
当一个版本控制系统支持多种协议时,在下载的时候会依次尝试各种协议。例如,Git下载会尝试https://,然后是git+ssh://。
By default, downloads are restricted to known secure protocols (e.g. https, ssh). To override this setting for Git downloads, the GIT_ALLOW_PROTOCOL environment variable can be set (For more details see: ‘go help environment’).
默认情况下,下载被限制在已知的安全协议上(例如 https、ssh)。要覆盖这一设置,可以设置GIT_ALLOW_PROTOCOL环境变量(更多细节见:“go help environment”)。
If the import path is not a known code hosting site and also lacks a version control qualifier, the go tool attempts to fetch the import over https/http and looks for a tag in the document’s HTML
.如果导入路径不是一个已知的代码托管网站,并且缺乏一个版本控制限定符,go工具会尝试通过https/http来获取导入,并在文档的HTML
中寻找一个标签。The meta tag has the form:
这个 meta 的形式是:
|
|
The import-prefix is the import path corresponding to the repository root. It must be a prefix or an exact match of the package being fetched with “go get”. If it’s not an exact match, another http request is made at the prefix to verify the tags match.
import-prefix 是对应于版本库根的导入路径。它必须是被 “go get “获取的包的前缀或完全匹配。如果不是完全匹配,会在前缀处发出另一个http请求,以验证标签的匹配。
The meta tag should appear as early in the file as possible. In particular, it should appear before any raw JavaScript or CSS, to avoid confusing the go command’s restricted parser.
元标签应该尽可能早地出现在文件中。特别是,它应该出现在任何原始JavaScript或CSS之前,以避免混淆go命令的限制性分析器。
The vcs is one of “bzr”, “fossil”, “git”, “hg”, “svn”.
vcs是 “bzr”、“fossil”、“git”、“hg”、“svn “中的一个。
The repo-root is the root of the version control system containing a scheme and not containing a .vcs qualifier.
repo-root是包含一个方案的版本控制系统的根,不包含.vcs限定符。
For example,
比如说,
|
|
will result in the following requests:
将导致以下请求:
https://example.org/pkg/foo?go-get=1 (preferred)
http://example.org/pkg/foo?go-get=1 (fallback, only with use of correctly set GOINSECURE)
If that page contains the meta tag
如果该页面包含meta
|
|
the go tool will verify that https://example.org/?go-get=1 contains the same meta tag and then git clone https://code.org/r/p/exproj into GOPATH/src/example.org.
go工具将验证https://example.org/?go-get=1 是否包含相同的元标签,然后git克隆https://code.org/r/p/exproj 到GOPATH/src/example.org。
When using GOPATH, downloaded packages are written to the first directory listed in the GOPATH environment variable. (See ‘go help gopath-get’ and ‘go help gopath’.)
当使用GOPATH时,下载的包被写入GOPATH环境变量中列出的第一个目录。(参见 “go help gopath-get “和 “go help gopath”)。
When using modules, downloaded packages are stored in the module cache. See https://golang.org/ref/mod#module-cache.
当使用模块时,下载的包被存储在模块缓存中。参见https://golang.org/ref/mod#module-cache。
When using modules, an additional variant of the go-import meta tag is recognized and is preferred over those listing version control systems. That variant uses “mod” as the vcs in the content value, as in:
当使用模块时,go-import元标签的另一个变体被识别,并且比那些列出版本控制系统的变体更受欢迎。该变体在内容值中使用 “mod “作为vcs,如:。
|
|
This tag means to fetch modules with paths beginning with example.org from the module proxy available at the URL https://code.org/moduleproxy. See https://golang.org/ref/mod#goproxy-protocol for details about the proxy protocol.
这个标签意味着从URL https://code.org/moduleproxy上的模块代理中获取路径以example.org开头的模块。关于代理协议的细节,见https://golang.org/ref/mod#goproxy-protocol。
Import path checking 导入路径检查
When the custom import path feature described above redirects to a known code hosting site, each of the resulting packages has two possible import paths, using the custom domain or the known hosting site.
当上面描述的自定义导入路径功能重定向到一个已知的代码托管网站时,产生的每个包都有两个可能的导入路径,使用自定义域名或已知托管网站。
A package statement is said to have an “import comment” if it is immediately followed (before the next newline) by a comment of one of these two forms:
如果一个包的语句后面(在下一个换行之前)紧跟着这两种形式的注释,则被称为有一个 “导入注释”:
package math // import "path"
package math /* import "path" */
The go command will refuse to install a package with an import comment unless it is being referred to by that import path. In this way, import comments let package authors make sure the custom import path is used and not a direct path to the underlying code hosting site.
go命令将拒绝安装带有导入注释的包,除非它被该导入路径所引用。通过这种方式,导入注释让包作者确保使用自定义的导入路径,而不是直接指向底层代码托管网站的路径。
Import path checking is disabled for code found within vendor trees. This makes it possible to copy code into alternate locations in vendor trees without needing to update import comments.
对于在供应商树中发现的代码,导入路径检查被禁用。这使得将代码复制到供应商树中的其他位置成为可能,而不需要更新导入注释。
Import path checking is also disabled when using modules. Import path comments are obsoleted by the go.mod file’s module statement.
当使用模块时,导入路径检查也被禁用。导入路径注释被go.mod文件的模块声明所取代。
See https://golang.org/s/go14customimport for details.
详见https://golang.org/s/go14customimport。
Modules, module versions, and more 模块、模块版本,以及更多
Modules are how Go manages dependencies.
模块是Go管理依赖关系的方式。
A module is a collection of packages that are released, versioned, and distributed together. Modules may be downloaded directly from version control repositories or from module proxy servers.
一个模块是一个包的集合,它被发布、版本化,并一起分发。模块可以直接从版本控制库或模块代理服务器上下载。
For a series of tutorials on modules, see https://golang.org/doc/tutorial/create-module.
关于模块的一系列教程,见https://golang.org/doc/tutorial/create-module。
For a detailed reference on modules, see https://golang.org/ref/mod.
关于模块的详细参考资料,见https://golang.org/ref/mod。
By default, the go command may download modules from https://proxy.golang.org. It may authenticate modules using the checksum database at https://sum.golang.org. Both services are operated by the Go team at Google. The privacy policies for these services are available at https://proxy.golang.org/privacy and https://sum.golang.org/privacy, respectively.
默认情况下,go命令可以从https://proxy.golang.org 下载模块。它可以使用 https://sum.golang.org 的校验和数据库来验证模块。这两项服务都是由Google的Go团队运营的。这些服务的隐私政策分别在 https://proxy.golang.org/privacy 和 https://sum.golang.org/privacy 上提供。
The go command’s download behavior may be configured using GOPROXY, GOSUMDB, GOPRIVATE, and other environment variables. See ‘go help environment’ and https://golang.org/ref/mod#private-module-privacy for more information.
go命令的下载行为可以通过GOPROXY、GOSUMDB、GOPRIVATE和其他环境变量进行配置。更多信息见 “go help environment “和https://golang.org/ref/mod#private-module-privacy。
Module authentication using go.sum 使用go.sum进行模块认证
When the go command downloads a module zip file or go.mod file into the module cache, it computes a cryptographic hash and compares it with a known value to verify the file hasn’t changed since it was first downloaded. Known hashes are stored in a file in the module root directory named go.sum. Hashes may also be downloaded from the checksum database depending on the values of GOSUMDB, GOPRIVATE, and GONOSUMDB.
当go命令下载一个模块压缩文件或go.mod文件到模块缓存中时,它会计算一个加密哈希值,并与一个已知值进行比较,以验证该文件自首次下载以来没有变化。已知的哈希值存储在模块根目录下一个名为go.sum的文件中。哈希值也可以根据GOSUMDB、GOPRIVATE和GONOSUMDB的值从校验数据库下载。
For details, see https://golang.org/ref/mod#authenticating.
详情请见https://golang.org/ref/mod#authenticating。
Package lists and patterns 包列表和模式
Many commands apply to a set of packages:
许多命令适用于一组包:
|
|
Usually, [packages] is a list of import paths.
通常,[packages]是一个导入路径的列表。
An import path that is a rooted path or that begins with a . or .. element is interpreted as a file system path and denotes the package in that directory.
一个导入路径如果是一个有根的路径或者以.或.元素开头,则被解释为一个文件系统路径,并表示该目录下的包。
Otherwise, the import path P denotes the package found in the directory DIR/src/P for some DIR listed in the GOPATH environment variable (For more details see: ‘go help gopath’).
否则,导入路径P表示在GOPATH环境变量中列出的某个DIR的目录DIR/src/P中找到的包(更多细节见:‘go help gopath’)。
If no import paths are given, the action applies to the package in the current directory.
如果没有给出导入路径,该动作适用于当前目录下的包。
There are four reserved names for paths that should not be used for packages to be built with the go tool:
有四个保留的路径名称,它们不应该被用于用go工具构建的包:
- “main” denotes the top-level package in a stand-alone executable.
- “main “表示一个独立的可执行程序中的顶级包。
- “all” expands to all packages found in all the GOPATH trees. For example, ‘go list all’ lists all the packages on the local system. When using modules, “all” expands to all packages in the main module and their dependencies, including dependencies needed by tests of any of those.
- “all “扩展到所有GOPATH树中发现的所有包。例如,“go list all “列出了本地系统中的所有包。当使用模块时,“all “扩展到主模块中的所有包和它们的依赖项,包括任何一个模块的测试所需要的依赖项。
- “std” is like all but expands to just the packages in the standard Go library.
- “std “与all类似,但只扩展到标准Go库中的包。
- “cmd” expands to the Go repository’s commands and their internal libraries.
- cmd “扩展到 Go 仓库的命令和它们的内部库。
Import paths beginning with “cmd/” only match source code in the Go repository.
以 “cmd/“开头的导入路径只匹配 Go 代码库中的源代码。
An import path is a pattern if it includes one or more “…” wildcards, each of which can match any string, including the empty string and strings containing slashes. Such a pattern expands to all package directories found in the GOPATH trees with names matching the patterns.
如果一个导入路径包含一个或多个”… “通配符,那么它就是一个模式,每个通配符可以匹配任何字符串,包括空字符串和包含斜线的字符串。这样的模式会扩展到GOPATH树中发现的所有名称与模式相匹配的包目录。
To make common patterns more convenient, there are two special cases. First, /… at the end of the pattern can match an empty string, so that net/… matches both net and packages in its subdirectories, like net/http. Second, any slash-separated pattern element containing a wildcard never participates in a match of the “vendor” element in the path of a vendored package, so that ./… does not match packages in subdirectories of ./vendor or ./mycode/vendor, but ./vendor/… and ./mycode/vendor/… do. Note, however, that a directory named vendor that itself contains code is not a vendored package: cmd/vendor would be a command named vendor, and the pattern cmd/… matches it. See golang.org/s/go15vendor for more about vendoring.
为了使常用模式更加方便,有两种特殊情况。首先,模式末尾的/…可以匹配一个空字符串,所以net/…可以同时匹配net和其子目录中的包,如net/http。其次,任何包含通配符的斜线分隔的模式元素都不会参与匹配被卖掉的包的路径中的 “vendor “元素,所以./…不匹配./vendor或./mycode/vendor子目录中的包,但./vendor/…和./mycode/vendor/…可以。但是请注意,一个名为vendor的目录本身包含的代码并不是一个vendored包:cmd/vendor将是一个名为vendor的命令,模式cmd/…与之匹配。参见 golang.org/s/go15vendor 了解更多关于 vendoring 的信息。
An import path can also name a package to be downloaded from a remote repository. Run ‘go help importpath’ for details.
一个导入路径也可以命名一个要从远程仓库下载的包。运行 “go help importpath “以了解详情。
Every package in a program must have a unique import path. By convention, this is arranged by starting each path with a unique prefix that belongs to you. For example, paths used internally at Google all begin with ‘google’, and paths denoting remote repositories begin with the path to the code, such as ‘github.com/user/repo’.
一个程序中的每个包都必须有一个唯一的导入路径。根据惯例,这是以属于你的独特前缀开始每个路径的安排。例如,谷歌内部使用的路径都以 “google “开头,而表示远程存储库的路径则以代码的路径开头,如 “github.com/user/repo”。
Packages in a program need not have unique package names, but there are two reserved package names with special meaning. The name main indicates a command, not a library. Commands are built into binaries and cannot be imported. The name documentation indicates documentation for a non-Go program in the directory. Files in package documentation are ignored by the go command.
程序中的包不需要有唯一的包名,但有两个保留的包名具有特殊意义。main这个名字表示一个命令,而不是一个库。命令是内置在二进制文件中的,不能被导入。文件名表示目录中的非围棋程序的文件。包文件中的文件会被go命令忽略。
As a special case, if the package list is a list of .go files from a single directory, the command is applied to a single synthesized package made up of exactly those files, ignoring any build constraints in those files and ignoring any other files in the directory.
作为一种特殊情况,如果包列表是一个单一目录下的.go文件列表,则该命令将应用于由这些文件组成的单一合成包,忽略这些文件中的任何构建约束,并忽略该目录中的任何其他文件。
Directory and file names that begin with “.” or “_” are ignored by the go tool, as are directories named “testdata”.
以”. “或”_“开头的目录和文件名会被go工具忽略,名为 “testdata “的目录也是如此。
Configuration for downloading non-public code 下载非公开代码的配置
The go command defaults to downloading modules from the public Go module mirror at proxy.golang.org. It also defaults to validating downloaded modules, regardless of source, against the public Go checksum database at sum.golang.org. These defaults work well for publicly available source code.
go命令默认从proxy.golang.org上的公共Go模块镜像下载模块。它也默认从sum.golang.org上的公共Go校验数据库验证下载的模块,无论其来源如何。这些默认值对于公开可用的源代码来说非常有效。
The GOPRIVATE environment variable controls which modules the go command considers to be private (not available publicly) and should therefore not use the proxy or checksum database. The variable is a comma-separated list of glob patterns (in the syntax of Go’s path.Match) of module path prefixes. For example,
GOPRIVATE 环境变量控制 go 命令认为哪些模块是私有的(不公开),因此不应该使用代理或校验数据库。该变量是一个以逗号分隔的模块路径前缀的glob模式列表(采用Go的path.Match语法)。例如,
GOPRIVATE=*.corp.example.com,rsc.io/private
causes the go command to treat as private any module with a path prefix matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, and rsc.io/private/quux.
导致go命令将任何路径前缀匹配这两种模式的模块视为私有,包括git.corp.example.com/xyzzy,rsc.io/private,以及rsc.io/private/quux。
For fine-grained control over module download and validation, the GONOPROXY and GONOSUMDB environment variables accept the same kind of glob list and override GOPRIVATE for the specific decision of whether to use the proxy and checksum database, respectively.
为了对模块下载和验证进行细粒度的控制,GONOPROXY和GONOSUMDB环境变量接受相同类型的glob列表,并在是否使用代理和校验数据库的具体决定中分别覆盖GOPRIVATE。
For example, if a company ran a module proxy serving private modules, users would configure go using:
例如,如果一个公司运行一个为私有模块服务的模块代理,用户将使用以下方式配置去:
GOPRIVATE=*.corp.example.com
GOPROXY=proxy.example.com
GONOPROXY=none
The GOPRIVATE variable is also used to define the “public” and “private” patterns for the GOVCS variable; see ‘go help vcs’. For that usage, GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths instead of module paths.
GOPRIVATE变量也被用来定义GOVCS变量的 “公共 “和 “私人 “模式;见 “go help vcs”。对于这种用法,GOPRIVATE甚至在GOPATH模式下也适用。在这种情况下,它匹配导入路径而不是模块路径。
The ‘go env -w’ command (see ‘go help env’) can be used to set these variables for future go command invocations.
go env -w “命令(见 “go help env”)可以用来为未来的go命令调用设置这些变量。
For more details, see https://golang.org/ref/mod#private-modules.
更多细节,见https://golang.org/ref/mod#private-modules。
Testing flags 测试标志
The ‘go test’ command takes both flags that apply to ‘go test’ itself and flags that apply to the resulting test binary.
go test “命令包括适用于 “go test “本身的标志和适用于结果测试二进制的标志。
Several of the flags control profiling and write an execution profile suitable for “go tool pprof”; run “go tool pprof -h” for more information. The –alloc_space, –alloc_objects, and –show_bytes options of pprof control how the information is presented.
其中一些标志控制剖析和编写适合于 “go tool pprof “的执行配置文件;运行 “go tool pprof -h “以获得更多信息。pprof的–alloc_space、–alloc_objects和–show_bytes选项控制信息的呈现方式。
The following flags are recognized by the ‘go test’ command and control the execution of any test:
以下标志可以被 “go test “命令识别,并控制任何测试的执行:
-bench regexp
Run only those benchmarks matching a regular expression.
By default, no benchmarks are run.
To run all benchmarks, use '-bench .' or '-bench=.'.
The regular expression is split by unbracketed slash (/)
characters into a sequence of regular expressions, and each
part of a benchmark's identifier must match the corresponding
element in the sequence, if any. Possible parents of matches
are run with b.N=1 to identify sub-benchmarks. For example,
given -bench=X/Y, top-level benchmarks matching X are run
with b.N=1 to find any sub-benchmarks matching Y, which are
then run in full.
-benchtime t
Run enough iterations of each benchmark to take t, specified
as a time.Duration (for example, -benchtime 1h30s).
The default is 1 second (1s).
The special syntax Nx means to run the benchmark N times
(for example, -benchtime 100x).
-count n
Run each test, benchmark, and fuzz seed n times (default 1).
If -cpu is set, run n times for each GOMAXPROCS value.
Examples are always run once. -count does not apply to
fuzz tests matched by -fuzz.
-cover
Enable coverage analysis.
Note that because coverage works by annotating the source
code before compilation, compilation and test failures with
coverage enabled may report line numbers that don't correspond
to the original sources.
-covermode set,count,atomic
Set the mode for coverage analysis for the package[s]
being tested. The default is "set" unless -race is enabled,
in which case it is "atomic".
The values:
set: bool: does this statement run?
count: int: how many times does this statement run?
atomic: int: count, but correct in multithreaded tests;
significantly more expensive.
Sets -cover.
-coverpkg pattern1,pattern2,pattern3
Apply coverage analysis in each test to packages matching the patterns.
The default is for each test to analyze only the package being tested.
See 'go help packages' for a description of package patterns.
Sets -cover.
-cpu 1,2,4
Specify a list of GOMAXPROCS values for which the tests, benchmarks or
fuzz tests should be executed. The default is the current value
of GOMAXPROCS. -cpu does not apply to fuzz tests matched by -fuzz.
-failfast
Do not start new tests after the first test failure.
-fuzz regexp
Run the fuzz test matching the regular expression. When specified,
the command line argument must match exactly one package within the
main module, and regexp must match exactly one fuzz test within
that package. Fuzzing will occur after tests, benchmarks, seed corpora
of other fuzz tests, and examples have completed. See the Fuzzing
section of the testing package documentation for details.
-fuzztime t
Run enough iterations of the fuzz target during fuzzing to take t,
specified as a time.Duration (for example, -fuzztime 1h30s).
The default is to run forever.
The special syntax Nx means to run the fuzz target N times
(for example, -fuzztime 1000x).
-fuzzminimizetime t
Run enough iterations of the fuzz target during each minimization
attempt to take t, as specified as a time.Duration (for example,
-fuzzminimizetime 30s).
The default is 60s.
The special syntax Nx means to run the fuzz target N times
(for example, -fuzzminimizetime 100x).
-json
Log verbose output and test results in JSON. This presents the
same information as the -v flag in a machine-readable format.
-list regexp
List tests, benchmarks, fuzz tests, or examples matching the regular
expression. No tests, benchmarks, fuzz tests, or examples will be run.
This will only list top-level tests. No subtest or subbenchmarks will be
shown.
-parallel n
Allow parallel execution of test functions that call t.Parallel, and
fuzz targets that call t.Parallel when running the seed corpus.
The value of this flag is the maximum number of tests to run
simultaneously.
While fuzzing, the value of this flag is the maximum number of
subprocesses that may call the fuzz function simultaneously, regardless of
whether T.Parallel is called.
By default, -parallel is set to the value of GOMAXPROCS.
Setting -parallel to values higher than GOMAXPROCS may cause degraded
performance due to CPU contention, especially when fuzzing.
Note that -parallel only applies within a single test binary.
The 'go test' command may run tests for different packages
in parallel as well, according to the setting of the -p flag
(see 'go help build').
-run regexp
Run only those tests, examples, and fuzz tests matching the regular
expression. For tests, the regular expression is split by unbracketed
slash (/) characters into a sequence of regular expressions, and each
part of a test's identifier must match the corresponding element in
the sequence, if any. Note that possible parents of matches are
run too, so that -run=X/Y matches and runs and reports the result
of all tests matching X, even those without sub-tests matching Y,
because it must run them to look for those sub-tests.
-short
Tell long-running tests to shorten their run time.
It is off by default but set during all.bash so that installing
the Go tree can run a sanity check but not spend time running
exhaustive tests.
-shuffle off,on,N
Randomize the execution order of tests and benchmarks.
It is off by default. If -shuffle is set to on, then it will seed
the randomizer using the system clock. If -shuffle is set to an
integer N, then N will be used as the seed value. In both cases,
the seed will be reported for reproducibility.
-timeout d
If a test binary runs longer than duration d, panic.
If d is 0, the timeout is disabled.
The default is 10 minutes (10m).
-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.
-vet list
Configure the invocation of "go vet" during "go test"
to use the comma-separated list of vet checks.
If list is empty, "go test" runs "go vet" with a curated list of
checks believed to be always worth addressing.
If list is "off", "go test" does not run "go vet" at all.
The following flags are also recognized by ‘go test’ and can be used to profile the tests during execution:
以下标志也可以被 “go test “识别,并可以在执行过程中用于描述测试:
-benchmem
Print memory allocation statistics for benchmarks.
-blockprofile block.out
Write a goroutine blocking profile to the specified file
when all tests are complete.
Writes test binary as -c would.
-blockprofilerate n
Control the detail provided in goroutine blocking profiles by
calling runtime.SetBlockProfileRate with n.
See 'go doc runtime.SetBlockProfileRate'.
The profiler aims to sample, on average, one blocking event every
n nanoseconds the program spends blocked. By default,
if -test.blockprofile is set without this flag, all blocking events
are recorded, equivalent to -test.blockprofilerate=1.
-coverprofile cover.out
Write a coverage profile to the file after all tests have passed.
Sets -cover.
-cpuprofile cpu.out
Write a CPU profile to the specified file before exiting.
Writes test binary as -c would.
-memprofile mem.out
Write an allocation profile to the file after all tests have passed.
Writes test binary as -c would.
-memprofilerate n
Enable more precise (and expensive) memory allocation profiles by
setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
To profile all memory allocations, use -test.memprofilerate=1.
-mutexprofile mutex.out
Write a mutex contention profile to the specified file
when all tests are complete.
Writes test binary as -c would.
-mutexprofilefraction n
Sample 1 in n stack traces of goroutines holding a
contended mutex.
-outputdir directory
Place output files from profiling in the specified directory,
by default the directory in which "go test" is running.
-trace trace.out
Write an execution trace to the specified file before exiting.
Each of these flags is also recognized with an optional ’test.’ prefix, as in -test.v. When invoking the generated test binary (the result of ‘go test -c’) directly, however, the prefix is mandatory.
当直接调用生成的测试二进制文件(“go test -c “的结果)时,前缀是强制性的。
The ‘go test’ command rewrites or removes recognized flags, as appropriate, both before and after the optional package list, before invoking the test binary.
在调用测试二进制文件之前,“go test “命令会根据情况改写或删除公认的标志,包括在可选的包列表之前和之后。
For instance, the command
例如,命令
go test -v -myflag testdata -cpuprofile=prof.out -x
will compile the test binary and then run it as
将编译测试二进制文件,然后作为
pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
(The -x flag is removed because it applies only to the go command’s execution, not to the test itself.)
(-x标志被删除,因为它只适用于go命令的执行,而不是测试本身)。
The test flags that generate profiles (other than for coverage) also leave the test binary in pkg.test for use when analyzing the profiles.
产生配置文件的测试标志(除覆盖率外)也会在pkg.test中留下测试二进制文件,以便分析配置文件时使用。
When ‘go test’ runs a test binary, it does so from within the corresponding package’s source code directory. Depending on the test, it may be necessary to do the same when invoking a generated test binary directly. Because that directory may be located within the module cache, which may be read-only and is verified by checksums, the test must not write to it or any other directory within the module unless explicitly requested by the user (such as with the -fuzz flag, which writes failures to testdata/fuzz).
当’go test’运行一个测试二进制文件时,它是从相应包的源代码目录中进行的。根据测试的情况,在直接调用生成的测试二进制文件时,可能也需要这样做。因为该目录可能位于模块缓存中,而模块缓存可能是只读的,并由校验和验证,除非用户明确要求,否则测试不能写到它或模块中的任何其他目录(比如用-fuzz标志,将故障写到testdata/fuzz)。
The command-line package list, if present, must appear before any flag not known to the go test command. Continuing the example above, the package list would have to appear before -myflag, but could appear on either side of -v.
命令行包列表,如果存在,必须出现在任何不为go test命令所知的标志之前。继续上面的例子,包列表必须出现在-myflag之前,但可以出现在-v的任何一侧。
When ‘go test’ runs in package list mode, ‘go test’ caches successful package test results to avoid unnecessary repeated running of tests. To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly is to use -count=1.
当 “go test “在包列表模式下运行时,“go test “会缓存成功的包测试结果,以避免不必要地重复运行测试。要禁用测试缓存,请使用除可缓存标志以外的任何测试标志或参数。明确禁用测试缓存的惯用方法是使用-count=1。
To keep an argument for a test binary from being interpreted as a known flag or a package name, use -args (see ‘go help test’) which passes the remainder of the command line through to the test binary uninterpreted and unaltered.
为了防止测试二进制文件的参数被解释为已知的标志或包名,使用 -args (见 ‘go help test’),它将命令行的其余部分传递给测试二进制文件,不被解释和改变。
For instance, the command
例如,命令
|
|
will compile the test binary and then run it as
将编译测试二进制文件,然后作为
|
|
Similarly,
类似地,
|
|
will compile the test binary and then run it as
将编译测试二进制文件,然后以
pkg.test math
In the first example, the -x and the second -v are passed through to the test binary unchanged and with no effect on the go command itself. In the second example, the argument math is passed through to the test binary, instead of being interpreted as the package list.
在第一个例子中,-x和第二个-v被传递到测试二进制文件中,没有改变,对go命令本身没有影响。在第二个例子中,参数math被传递到测试二进制文件中,而不是被解释为包列表。
Testing functions 测试函数
The ‘go test’ command expects to find test, benchmark, and example functions in the “*_test.go” files corresponding to the package under test.
go test “命令希望在与被测包对应的 “*_test.go “文件中找到测试、基准和示例函数。
A test function is one named TestXxx (where Xxx does not start with a lower case letter) and should have the signature,
一个测试函数被命名为TestXxx(其中Xxx不以小写字母开头),并且应该有这样的签名。
|
|
A benchmark function is one named BenchmarkXxx and should have the signature,
基准函数是一个名为BenchmarkXxx的函数,应该有这样的签名,
|
|
A fuzz test is one named FuzzXxx and should have the signature,
一个模糊测试是一个名为FuzzXxx的测试,应该有这样的签名,
|
|
An example function is similar to a test function but, instead of using *testing.T to report success or failure, prints output to os.Stdout. If the last comment in the function starts with “Output:” then the output is compared exactly against the comment (see examples below). If the last comment begins with “Unordered output:” then the output is compared to the comment, however the order of the lines is ignored. An example with no such comment is compiled but not executed. An example with no text after “Output:” is compiled, executed, and expected to produce no output.
一个示例函数类似于一个测试函数,但不是用*testing.T来报告成功或失败,而是将输出打印到os.Stdout。如果函数中的最后一个注释以 “Output: “开头,那么输出就会与注释完全比较(见下面的例子)。如果最后一条注释以 “无序输出: “开始,那么输出将与注释进行比较,但是行的顺序将被忽略。一个没有这种注释的例子会被编译,但不会被执行。一个在 “Output: “之后没有文本的例子被编译、执行,并且预期不会产生任何输出。
Godoc displays the body of ExampleXxx to demonstrate the use of the function, constant, or variable Xxx. An example of a method M with receiver type T or *T is named ExampleT_M. There may be multiple examples for a given function, constant, or variable, distinguished by a trailing _xxx, where xxx is a suffix not beginning with an upper case letter.
Godoc显示ExampleXxx的正文,演示函数、常数或变量Xxx的使用。一个带有接收器类型T或*T的方法M的例子被命名为ExampleT_M。一个给定的函数、常量或变量可能有多个例子,用尾部的_xxx来区分,其中xxx是一个非大写字母开头的后缀。
Here is an example of an example:
下面是一个例子的例子:
|
|
Here is another example where the ordering of the output is ignored:
这里是另一个例子,输出的顺序被忽略了:
|
|
The entire test file is presented as the example when it contains a single example function, at least one other function, type, variable, or constant declaration, and no tests, benchmarks, or fuzz tests.
当整个测试文件包含一个示例函数,至少有一个其他函数、类型、变量或常量声明,并且没有测试、基准或模糊测试时,该文件将作为示例呈现。
See the documentation of the testing package for more information.
更多信息请参见测试包的文档。
Controlling version control with GOVCS 用GOVCS控制版本控制
The ‘go get’ command can run version control commands like git to download imported code. This functionality is critical to the decentralized Go package ecosystem, in which code can be imported from any server, but it is also a potential security problem, if a malicious server finds a way to cause the invoked version control command to run unintended code.
go get “命令可以运行版本控制命令,如git来下载导入的代码。这个功能对于分散的Go包生态系统至关重要,因为代码可以从任何服务器上导入,但这也是一个潜在的安全问题,如果一个恶意的服务器找到一种方法,使调用的版本控制命令运行非预期的代码。
To balance the functionality and security concerns, the ‘go get’ command by default will only use git and hg to download code from public servers. But it will use any known version control system (bzr, fossil, git, hg, svn) to download code from private servers, defined as those hosting packages matching the GOPRIVATE variable (see ‘go help private’). The rationale behind allowing only Git and Mercurial is that these two systems have had the most attention to issues of being run as clients of untrusted servers. In contrast, Bazaar, Fossil, and Subversion have primarily been used in trusted, authenticated environments and are not as well scrutinized as attack surfaces.
为了平衡功能和安全问题,“go get “命令默认只使用git和hg从公共服务器下载代码。但它会使用任何已知的版本控制系统(bzr、fossil、git、hg、svn)从私有服务器下载代码,私有服务器的定义是那些与GOPRIVATE变量相匹配的托管包(见’go help private’)。只允许Git和Mercurial的理由是,这两个系统作为不受信任的服务器的客户端运行的问题最受关注。相比之下,Bazaar、Fossil和Subversion主要用于可信的、经过验证的环境中,没有被作为攻击面进行仔细检查。
The version control command restrictions only apply when using direct version control access to download code. When downloading modules from a proxy, ‘go get’ uses the proxy protocol instead, which is always permitted. By default, the ‘go get’ command uses the Go module mirror (proxy.golang.org) for public packages and only falls back to version control for private packages or when the mirror refuses to serve a public package (typically for legal reasons). Therefore, clients can still access public code served from Bazaar, Fossil, or Subversion repositories by default, because those downloads use the Go module mirror, which takes on the security risk of running the version control commands using a custom sandbox.
版本控制命令的限制只适用于使用直接版本控制访问下载代码时。当从代理处下载模块时,‘go get’使用代理协议代替,这总是被允许的。默认情况下,‘go get’命令使用Go模块镜像(proxy.golang.org)下载公共包,只有在下载私有包或镜像拒绝提供公共包时(通常是出于法律原因)才会返回到版本控制。因此,客户端仍然可以访问Bazaar、Fossil或Subversion库提供的公共代码,因为这些下载使用Go模块镜像,它承担了使用自定义沙盒运行版本控制命令的安全风险。
The GOVCS variable can be used to change the allowed version control systems for specific packages (identified by a module or import path). The GOVCS variable applies when building package in both module-aware mode and GOPATH mode. When using modules, the patterns match against the module path. When using GOPATH, the patterns match against the import path corresponding to the root of the version control repository.
GOVCS变量可以用来改变特定包(由模块或导入路径识别)所允许的版本控制系统。GOVCS变量适用于在模块感知模式和GOPATH模式下构建包。当使用模块时,这些模式与模块路径相匹配。当使用GOPATH时,模式与版本控制库的根部对应的导入路径相匹配。
The general form of the GOVCS setting is a comma-separated list of pattern:vcslist rules. The pattern is a glob pattern that must match one or more leading elements of the module or import path. The vcslist is a pipe-separated list of allowed version control commands, or “all” to allow use of any known command, or “off” to disallow all commands. Note that if a module matches a pattern with vcslist “off”, it may still be downloaded if the origin server uses the “mod” scheme, which instructs the go command to download the module using the GOPROXY protocol. The earliest matching pattern in the list applies, even if later patterns might also match.
GOVCS 设置的一般形式是一个逗号分隔的 pattern:vcslist 规则列表。pattern是一个glob模式,必须与模块或导入路径的一个或多个前导元素相匹配。vcslist是一个用管道分隔的允许使用的版本控制命令的列表,或者用 “all “来允许使用任何已知的命令,或者用 “off “来不允许使用所有命令。注意,如果一个模块与vcslist “off “的模式相匹配,如果原服务器使用 “mod “方案,它仍然可以下载,该方案指示go命令使用GOPROXY协议下载该模块。列表中最早的匹配模式适用,即使后来的模式也可能匹配。
For example, consider:
例如,考虑:
GOVCS=github.com:git,evil.com:off,*:git|hg
With this setting, code with a module or import path beginning with github.com/ can only use git; paths on evil.com cannot use any version control command, and all other paths (* matches everything) can use only git or hg.
有了这个设置,模块或导入路径以github.com/开头的代码只能使用git;evil.com上的路径不能使用任何版本控制命令,而所有其他路径(*匹配所有)只能使用git或hg。
The special patterns “public” and “private” match public and private module or import paths. A path is private if it matches the GOPRIVATE variable; otherwise it is public.
特殊模式 “public “和 “private “匹配公共和私人模块或导入路径。如果一个路径与GOPRIVATE变量相匹配,那么它就是私有的;否则就是公共的。
If no rules in the GOVCS variable match a particular module or import path, the ‘go get’ command applies its default rule, which can now be summarized in GOVCS notation as ‘public:git|hg,private:all’.
如果GOVCS变量中没有规则与某个特定的模块或导入路径相匹配,“go get “命令会应用其默认规则,现在可以用GOVCS的符号将其概括为 “public:git|hg,private:all”。
To allow unfettered use of any version control system for any package, use:
要允许任何包不受限制地使用任何版本控制系统,请使用:
GOVCS=*:all
To disable all use of version control, use:
要禁用所有版本控制的使用,请使用:
GOVCS=*:off
The ‘go env -w’ command (see ‘go help env’) can be used to set the GOVCS variable for future go command invocations.
go env -w “命令(见 “go help env”)可以用来设置GOVCS变量,以便今后调用go命令。
1.3.16 - godoc
godoc
Overview 概述
godoc 提取并生成Go程序的文档。
它以Web服务器的形式运行,并以网页的形式展示文档。
godoc -http=:6060
使用方法:
godoc [flag]
标志有:
-v
冗长的模式
-timestamps=true
显示目录列表中的时间戳
-index
启用标识符和全文搜索索引
(如果没有设置-index,则不显示搜索框)
-index_files=""
指定索引文件的glob模式;如果不是空的话。
索引是按照排序从这些文件中读取的。
-index_throttle=0.75
索引节流值;值为0意味着没有时间分配给索引器(索引器将永远不会完成),值为1.0意味着索引创建以全速运行(当索引建立时,其他goroutine可能没有时间)。
-index_interval=0
建立索引的时间间隔;值为0时,设置为5分钟,负值时,只在启动时建立一次索引。
-play=false
启用playground
-links=true
将标识符链接到它们的声明中
-write_index=false
将索引写到一个文件中;文件名必须用-index_files
-maxresults=10000
显示全文搜索结果的最大数量
(如果maxresults <= 0,则不建立全文索引)
-notes="BUG"
正则表达式匹配要显示的注释标记
(例如,"BUG|TODO", ".*")
-goroot=$GOROOT
Go的根目录
-http=addr
HTTP服务地址(例如,'127.0.0.1:6060'或只是':6060')
-templates=""
包含备用模板文件的目录;如果设置,该目录可以为$GOROOT/lib/godoc中的文件提供备用模板文件
-url=path
将HTTP请求提供的数据打印到标准输出中,该数据将由path提供。
-zip=""
提供文件系统服务的zip文件;如果为空则禁用
默认情况下,godoc 通过$GOROOT和$GOPATH(如果设置)查看它发现的包。这个行为可以通过使用-goroot标志提供一个替代的$GOROOT来改变。
当-index标志被设置时,一个搜索索引被维护。该索引在启动时被创建。
该索引包含标识符和全文搜索信息(可通过正则表达式搜索)。显示全文搜索结果的最大数量可以用-maxresults标志设置;如果设置为0,不显示全文搜索结果,只创建标识符索引,不创建全文搜索索引。
默认情况下,godoc使用系统的GOOS/GOARCH。你可以提供URL参数 “GOOS “和 “GOARCH”,为目标系统设置网页上的输出。
由godoc提供的网页的表现模式可以用 “m” URL参数控制;它接受一个用逗号分隔的标志名称列表作为值:
all 显示所有声明的文档,而不仅仅是导出的声明
methods show all embedded methods, not just those of unexported anonymous fields
显示所有嵌入的方法,而不仅仅是那些未导出的匿名字段的方法
src 显示原始源代码,而不是提取的文档
flat 显示使用完整路径的扁平(非缩进)目录列表
例如,https://golang.org/pkg/math/big/?m=all 显示big包的所有(而不仅仅是导出的)声明的文档。
默认情况下,godoc从底层操作系统的文件系统中提供文件。相反,可以通过-zip标志提供一个.zip文件,其中包含要服务的文件系统。存储在.zip文件中的文件路径必须使用斜线(’/’)作为路径分隔符;并且它们必须是无根的。$GOROOT(或-goroot)必须设置为包含Go根目录的.zip文件目录路径。例如,对于一个由命令创建的.zip文件:
zip -r go.zip $HOME/go
可以按以下方式运行godoc:
godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
godoc文档被转换为HTML或使用go/doc包转换为文本,具体规则见https://golang.org/pkg/go/doc/#ToHTML。godoc还显示可由测试包运行的示例代码;具体规则见https://golang.org/pkg/testing/#hdr-Examples。参见 “Godoc:记录Go代码”,了解如何为godoc写好注释:https://golang.org/doc/articles/godoc_documenting_go_code.html
已弃用:godoc不能选择要显示包的版本。相反,请使用golang.org/x/pkgsite/cmd/pkgsite。
1.3.17 - gofmt
gofmt
Overview 概述
Gofmt formats Go programs. It uses tabs for indentation and blanks for alignment. Alignment assumes that an editor is using a fixed-width font.
Gofmt可以格式化Go程序。它使用制表符来缩进,使用空白来对齐。对齐的前提是编辑器使用固定宽度的字体。
Without an explicit path, it processes the standard input. Given a file, it operates on that file; given a directory, it operates on all .go files in that directory, recursively. (Files starting with a period are ignored.) By default, gofmt prints the reformatted sources to standard output.
没有明确的路径,它处理标准输入。给定一个文件,它就对该文件进行操作;给定一个目录,它就对该目录中的所有.go文件进行递归操作。(以句号开头的文件被忽略。)默认情况下,gofmt将重新格式化的源文件打印到标准输出。
使用方法:
gofmt [flags] [path ...]
The flags are:
标志是:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
=> 不将重新格式化的源文件打印到标准输出。
如果一个文件的格式与gofmt的不同,则将差异打印到标准输出。到标准输出。
-e
Print all (including spurious) errors.
=> 打印所有(包括假的)错误。
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
=> 不打印重新格式化的来源到标准输出。
如果一个文件的格式与gofmt不同,则打印其名称
到标准输出。
-r rule
Apply the rewrite rule to the source before reformatting.
=> 在重新格式化前对源文件应用重写规则。
-s
Try to simplify code (after applying the rewrite rule, if any).
=> 尝试简化代码(在应用重写规则后,如果有的话)。
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.
=> 不将重新格式化的源文件打印到标准输出。
如果一个文件的格式与gofmt的不同,就用gofmt的版本覆盖它。 用gofmt的版本覆盖。如果在覆盖的过程中发生错误。 原始文件将从自动备份中恢复。
Debugging support:
调试支持:
-cpuprofile filename
Write cpu profile to the specified file.
The rewrite rule specified with the -r flag must be a string of the form:
用-r标志指定的重写规则必须是一个形式的字符串:
pattern -> replacement
Both pattern and replacement must be valid Go expressions. In the pattern, single-character lowercase identifiers serve as wildcards matching arbitrary sub-expressions; those expressions will be substituted for the same identifiers in the replacement.
pattern和replacement都必须是有效的Go表达式。在模式中,单字符小写标识符作为通配符匹配任意子表达式;这些表达式将被替换为替换中的相同标识符。
When gofmt reads from standard input, it accepts either a full Go program or a program fragment. A program fragment must be a syntactically valid declaration list, statement list, or expression. When formatting such a fragment, gofmt preserves leading indentation as well as leading and trailing spaces, so that individual sections of a Go program can be formatted by piping them through gofmt.
当gofmt从标准输入读取时,它接受一个完整的Go程序或程序片段。程序片段必须是一个语法上有效的声明列表、语句列表或表达式。当格式化这样的片段时,gofmt 会保留前导缩进以及前导和后导空格,因此 Go 程序的各个部分可以通过 gofmt 的管道来进行格式化。
Examples 例子
To check files for unnecessary parentheses:
检查文件是否有不必要的括号:
gofmt -r '(a) -> a' -l *.go
To remove the parentheses:
要删除括号:
gofmt -r '(a) -> a' -w *.go
To convert the package tree from explicit slice upper bounds to implicit ones:
将包树从明确的片断上界转换为隐含的上界:
gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src
The simplify command 简化命令
When invoked with -s gofmt will make the following source transformations where possible.
当与-s一起调用时,gofmt将尽可能地进行以下源转换。
An array, slice, or map composite literal of the form:
[]T{T{}, T{}}
will be simplified to:
[]T{{}, {}}
A slice expression of the form:
s[a:len(s)]
will be simplified to:
s[a:]
A range of the form:
for x, _ = range v {...}
will be simplified to:
for x = range v {...}
A range of the form:
for _ = range v {...}
will be simplified to:
for range v {...}
This may result in changes that are incompatible with earlier versions of Go.
这可能会导致与Go早期版本不兼容的变化。
Notes 注意事项
Bugs
- The implementation of -r is a bit slow.-r的实现有点慢。
- If -w fails, the restored original file may not have some of the original file attributes.如果-w失败,恢复的原始文件可能没有一些原始文件的属性。
1.3.18 - gofmt 2
gofmt
Gofmt formats Go programs. It uses tabs for indentation and blanks for alignment. Alignment assumes that an editor is using a fixed-width font.
Without an explicit path, it processes the standard input. Given a file, it operates on that file; given a directory, it operates on all .go files in that directory, recursively. (Files starting with a period are ignored.) By default, gofmt prints the reformatted sources to standard output.
Usage:
gofmt [flags] [path ...]
The flags are:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
-e
Print all (including spurious) errors.
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
-r rule
Apply the rewrite rule to the source before reformatting.
-s
Try to simplify code (after applying the rewrite rule, if any).
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.
Debugging support:
-cpuprofile filename
Write cpu profile to the specified file.
The rewrite rule specified with the -r flag must be a string of the form:
pattern -> replacement
Both pattern and replacement must be valid Go expressions. In the pattern, single-character lowercase identifiers serve as wildcards matching arbitrary sub-expressions; those expressions will be substituted for the same identifiers in the replacement.
When gofmt reads from standard input, it accepts either a full Go program or a program fragment. A program fragment must be a syntactically valid declaration list, statement list, or expression. When formatting such a fragment, gofmt preserves leading indentation as well as leading and trailing spaces, so that individual sections of a Go program can be formatted by piping them through gofmt.
Examples
To check files for unnecessary parentheses:
gofmt -r '(a) -> a' -l *.go
To remove the parentheses:
gofmt -r '(a) -> a' -w *.go
To convert the package tree from explicit slice upper bounds to implicit ones:
gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src
The simplify command
When invoked with -s gofmt will make the following source transformations where possible.
An array, slice, or map composite literal of the form:
[]T{T{}, T{}}
will be simplified to:
[]T{{}, {}}
A slice expression of the form:
s[a:len(s)]
will be simplified to:
s[a:]
A range of the form:
for x, _ = range v {...}
will be simplified to:
for x = range v {...}
A range of the form:
for _ = range v {...}
will be simplified to:
for range v {...}
This may result in changes that are incompatible with earlier versions of Go.
Notes
Bugs
- The implementation of -r is a bit slow.
- If -w fails, the restored original file may not have some of the original file attributes.
1.3.19 - link
link
Overview 概述
link,通常以 “go tool link “的形式调用,读取包 main 的 Go 存档或对象及其依赖项,并将它们组合成一个可执行的二进制文件。
Command Line 命令行
使用方法:
go tool link [flags] main.a
标志:
-B note
Add an ELF_NT_GNU_BUILD_ID note when using ELF.
The value should start with 0x and be an even number of hex digits.
=>在使用ELF时,添加一个ELF_NT_GNU_BUILD_ID注释。
这个值应该以0x开始,并且是一个偶数的十六进制数字。
-D address
Set data segment address.
=> 设置数据段地址。
-E entry
Set entry symbol name.
=> 设置条目符号名称。
-H type
Set executable format type.
The default format is inferred from GOOS and GOARCH.
On Windows, -H windowsgui writes a "GUI binary" instead of a "console binary."
=> 设置可执行格式类型。
默认格式是由GOOS和GOARCH推断出来的。
在Windows上,-H windowsgui 编写 "GUI binary",而不是 "console binary"。
-I interpreter
Set the ELF dynamic linker to use.
=> 设置要使用的 ELF 动态链接器。
-L dir1 -L dir2
Search for imported packages in dir1, dir2, etc,
after consulting $GOROOT/pkg/$GOOS_$GOARCH.
=> 在dir1、dir2等处搜索导入的软件包。
在查询$GOROOT/pkg/$GOOS_$GOARCH之后。
-R quantum
Set address rounding quantum.
=> 设置地址舍入量子。
-T address
Set text segment address.
=> 设置文本段地址。
-V
Print linker version and exit.
=> 打印链接器版本并退出。
-X importpath.name=value
Set the value of the string variable in importpath named name to value.
This is only effective if the variable is declared in the source code either uninitialized
or initialized to a constant string expression. -X will not work if the initializer makes
a function call or refers to other variables.
Note that before Go 1.5 this option took two separate arguments.
=> 将 importpath 中名为 name 的字符串变量的值设置为值。
只有当该变量在源代码中未被初始化或被初始化为常量字符串表达式时,这才有效。
或初始化为一个常量的字符串表达式。如果初始化器进行了函数调用或引用了其他变量,-X将不起作用。
函数调用或引用其他变量时,-X不起作用。
注意,在Go 1.5之前,这个选项需要两个单独的参数。
-a
Disassemble output.
=> 反汇编输出。
-asan
Link with C/C++ address sanitizer support.
=> 支持C/C++地址净化器的链接。
-buildid id
Record id as Go toolchain build id.
=> 记录ID作为Go工具链的构建ID。
-buildmode mode
Set build mode (default exe).
=> 设置构建模式(默认为 exe)。
-c
Dump call graphs.
=> 转储调用图。
-compressdwarf
Compress DWARF if possible (default true).
=> 如果可能的话,压缩DWARF(默认为true)。
-cpuprofile file
Write CPU profile to file.
=> 将CPU配置文件写到文件中。
-d
Disable generation of dynamic executables.
The emitted code is the same in either case; the option
controls only whether a dynamic header is included.
The dynamic header is on by default, even without any
references to dynamic libraries, because many common
system tools now assume the presence of the header.
=> 禁用动态可执行文件的生成。
在这两种情况下发出的代码都是一样的;
该选项只控制是否包含动态头。
动态头默认是打开的,即使没有任何对动态库的引用,
因为现在许多常见的系统工具都假定存在头。
-debugtramp int
Debug trampolines.
=>
-dumpdep
Dump symbol dependency graph.
=> 转储符号依赖图。
-extar ar
Set the external archive program (default "ar").
Used only for -buildmode=c-archive.
=> 设置外部存档程序(默认为 "ar")。
仅用于 -buildmode=c-archive。
-extld linker
Set the external linker (default "clang" or "gcc").
=> 设置外部链接器(默认为 "clang "或 "gcc")。
-extldflags flags
Set space-separated flags to pass to the external linker.
=> 设置以空格分隔的标志,传递给外部链接器。
-f
Ignore version mismatch in the linked archives.
=> 忽略链接存档中的版本不匹配。
-g
Disable Go package data checks.
=> 停用 Go 包的数据检查。
-importcfg file
Read import configuration from file.
In the file, set packagefile, packageshlib to specify import resolution.
=> 从 file 中读取导入配置。
在 file 中,设置packagefile、packageshlib来指定导入解析。
-installsuffix suffix
Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
instead of $GOROOT/pkg/$GOOS_$GOARCH.
=> 在$GOROOT/pkg/$GOOS_$GOARCH_suffix中寻找包
而不是在 $GOROOT/pkg/$GOOS_$GOARCH。
-k symbol
Set field tracking symbol. Use this flag when GOEXPERIMENT=fieldtrack is set.
=> 设置字段跟踪符号。当设置GOEXPERIMENT=fieldtrack时,使用此标志。
-libgcc file
Set name of compiler support library.
This is only used in internal link mode.
If not set, default value comes from running the compiler,
which may be set by the -extld option.
Set to "none" to use no support library.
=> 设置编译器支持库的名称。
这只在内部链接模式下使用。
如果不设置,默认值来自运行的编译器,
可以通过-extld选项设置。
设置为 "none"表示不使用支持库。
-linkmode mode
Set link mode (internal, external, auto).
This sets the linking mode as described in cmd/cgo/doc.go.
=> 设置链接模式(内部、外部、自动)。
这设置了cmd/cgo/doc.go中描述的链接模式。
-linkshared
Link against installed Go shared libraries (experimental).
=> 针对已安装的 Go 共享库进行链接(实验性)。
-memprofile file
Write memory profile to file.
=> 将内存配置文件写入 file。
-memprofilerate rate
Set runtime.MemProfileRate to rate.
=> 将 runtime.MemProfileRate 设置为 rate。
-msan
Link with C/C++ memory sanitizer support.
=> 支持用C/C++内存净化器进行链接。
-n
Dump symbol table.
=> 转储符号表。
-o file
Write output to file (default a.out, or a.out.exe on Windows).
=> 将输出写入 file(默认为a.out,或Windows下的a.out.exe)。
-pluginpath path
The path name used to prefix exported plugin symbols.
=> 用来给导出的插件符号加前缀的 path 名称。
-r dir1:dir2:...
Set the ELF dynamic linker search path.
=> 设置ELF动态链接器的搜索路径。
-race
Link with race detection libraries.
=> 用竞争检测库链接。
-s
Omit the symbol table and debug information.
=> 省略符号表和调试信息。
-shared
Generated shared object (implies -linkmode external; experimental).
=> 生成的共享对象(意味着-linkmode external; 实验性)。
-tmpdir dir
Write temporary files to dir.
Temporary files are only used in external linking mode.
=> 将临时文件写到 dir。
临时文件只在外部链接模式下使用。
-u
Reject unsafe packages.
=> 拒绝不安全的件包。
-v
Print trace of linker operations.
=> 打印链接器操作的痕迹。
-w
Omit the DWARF symbol table.
=> 省略DWARF符号表。
1.3.20 - nm
nm
Overview 概述
nm列出对象文件、存案或可执行文件所定义或使用的符号。
使用方法:
go tool nm [options] file...
默认输出为每个符号打印一行,使用三个空格分隔的字段给出地址(十六进制)、类型(一个字符)和符号的名称。这些类型是:
T text (code) segment symbol
=> 文本(代码)段符号
t static text segment symbol
=> 静态文本段符号
R read-only data segment symbol
=> 只读数据段符号
r static read-only data segment symbol
=> 静态只读数据段符号
D data segment symbol
=> 数据段符号
d static data segment symbol
=> 静态数据段符号
B bss segment symbol
=> bss 段符号
b static bss segment symbol
=> 静态bss 段符号
C constant address
=> 常量地址
U referenced but undefined symbol
=> 被引用但未定义的符号
按照既定惯例,未定义的符号(U类型)省略了地址。
以下这些选项(options )控制打印输出:
-n
an alias for -sort address (numeric),
for compatibility with other nm commands
=> 是 -sort 地址(数字)的别名,
为了与其他nm命令兼容
-size
print symbol size in decimal between address and type
=> 打印地址和类型之间的符号大小(十进制)。
-sort {address,name,none,size}
sort output in the given order (default name)
size orders from largest to smallest
=> 按照给定的顺序对输出进行排序(默认为名称)。
size的顺序从大到小排序
-type
print symbol type after name
=> 在名称之后打印符号类型
=== “doc.go”
```go linenums="1"
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Nm lists the symbols defined or used by an object file, archive, or executable.
//
// Usage:
//
// go tool nm [options] file...
//
// The default output prints one line per symbol, with three space-separated
// fields giving the address (in hexadecimal), type (a character), and name of
// the symbol. The types are:
//
// T text (code) segment symbol
// t static text segment symbol
// R read-only data segment symbol
// r static read-only data segment symbol
// D data segment symbol
// d static data segment symbol
// B bss segment symbol
// b static bss segment symbol
// C constant address
// U referenced but undefined symbol
//
// Following established convention, the address is omitted for undefined
// symbols (type U).
//
// The options control the printed output:
//
// -n
// an alias for -sort address (numeric),
// for compatibility with other nm commands
// -size
// print symbol size in decimal between address and type
// -sort {address,name,none,size}
// sort output in the given order (default name)
// size orders from largest to smallest
// -type
// print symbol type after name
package main
```
=== “nm.go”
```go linenums="1"
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"sort"
"cmd/internal/objfile"
)
const helpText = `usage: go tool nm [options] file...
-n
an alias for -sort address (numeric),
for compatibility with other nm commands
-size
print symbol size in decimal between address and type
-sort {address,name,none,size}
sort output in the given order (default name)
size orders from largest to smallest
-type
print symbol type after name
`
func usage() {
fmt.Fprintf(os.Stderr, helpText)
os.Exit(2)
}
var (
sortOrder = flag.String("sort", "name", "")
printSize = flag.Bool("size", false, "")
printType = flag.Bool("type", false, "")
filePrefix = false
)
func init() {
flag.Var(nflag(0), "n", "") // alias for -sort address
}
type nflag int
func (nflag) IsBoolFlag() bool {
return true
}
func (nflag) Set(value string) error {
if value == "true" {
*sortOrder = "address"
}
return nil
}
func (nflag) String() string {
if *sortOrder == "address" {
return "true"
}
return "false"
}
func main() {
log.SetFlags(0)
flag.Usage = usage
flag.Parse()
switch *sortOrder {
case "address", "name", "none", "size":
// ok
default:
fmt.Fprintf(os.Stderr, "nm: unknown sort order %q\n", *sortOrder)
os.Exit(2)
}
args := flag.Args()
filePrefix = len(args) > 1
if len(args) == 0 {
flag.Usage()
}
for _, file := range args {
nm(file)
}
os.Exit(exitCode)
}
var exitCode = 0
func errorf(format string, args ...any) {
log.Printf(format, args...)
exitCode = 1
}
func nm(file string) {
f, err := objfile.Open(file)
if err != nil {
errorf("%v", err)
return
}
defer f.Close()
w := bufio.NewWriter(os.Stdout)
entries := f.Entries()
var found bool
for _, e := range entries {
syms, err := e.Symbols()
if err != nil {
errorf("reading %s: %v", file, err)
}
if len(syms) == 0 {
continue
}
found = true
switch *sortOrder {
case "address":
sort.Slice(syms, func(i, j int) bool { return syms[i].Addr < syms[j].Addr })
case "name":
sort.Slice(syms, func(i, j int) bool { return syms[i].Name < syms[j].Name })
case "size":
sort.Slice(syms, func(i, j int) bool { return syms[i].Size > syms[j].Size })
}
for _, sym := range syms {
if len(entries) > 1 {
name := e.Name()
if name == "" {
fmt.Fprintf(w, "%s(%s):\t", file, "_go_.o")
} else {
fmt.Fprintf(w, "%s(%s):\t", file, name)
}
} else if filePrefix {
fmt.Fprintf(w, "%s:\t", file)
}
if sym.Code == 'U' {
fmt.Fprintf(w, "%8s", "")
} else {
fmt.Fprintf(w, "%8x", sym.Addr)
}
if *printSize {
fmt.Fprintf(w, " %10d", sym.Size)
}
fmt.Fprintf(w, " %c %s", sym.Code, sym.Name)
if *printType && sym.Type != "" {
fmt.Fprintf(w, " %s", sym.Type)
}
fmt.Fprintf(w, "\n")
}
}
if !found {
errorf("reading %s: no symbols", file)
}
w.Flush()
}
```
=== “nm_test.go”
```go linenums="1"
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build cgo
package main
import (
"runtime"
"testing"
)
func canInternalLink() bool {
switch runtime.GOOS {
case "aix":
return false
case "dragonfly":
return false
case "freebsd":
switch runtime.GOARCH {
case "arm64":
return false
}
case "linux":
switch runtime.GOARCH {
case "arm64", "loong64", "mips64", "mips64le", "mips", "mipsle", "ppc64", "ppc64le", "riscv64":
return false
}
case "openbsd":
switch runtime.GOARCH {
case "arm64", "mips64":
return false
}
case "windows":
switch runtime.GOARCH {
case "arm64":
return false
}
}
return true
}
func TestInternalLinkerCgoExec(t *testing.T) {
if !canInternalLink() {
t.Skip("skipping; internal linking is not supported")
}
testGoExec(t, true, false)
}
func TestExternalLinkerCgoExec(t *testing.T) {
testGoExec(t, true, true)
}
func TestCgoLib(t *testing.T) {
testGoLib(t, true)
}
```
=== “nm_cgo_test.go”
```go linenums="1"
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"internal/obscuretestdata"
"internal/testenv"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"text/template"
)
var testnmpath string // path to nm command created for testing purposes
// The TestMain function creates a nm command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
func testMain(m *testing.M) int {
if !testenv.HasGoBuild() {
return 0
}
tmpDir, err := os.MkdirTemp("", "TestNM")
if err != nil {
fmt.Println("TempDir failed:", err)
return 2
}
defer os.RemoveAll(tmpDir)
testnmpath = filepath.Join(tmpDir, "testnm.exe")
gotool, err := testenv.GoTool()
if err != nil {
fmt.Println("GoTool failed:", err)
return 2
}
out, err := exec.Command(gotool, "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
if err != nil {
fmt.Printf("go build -o %v cmd/nm: %v\n%s", testnmpath, err, string(out))
return 2
}
return m.Run()
}
func TestNonGoExecs(t *testing.T) {
t.Parallel()
testfiles := []string{
"debug/elf/testdata/gcc-386-freebsd-exec",
"debug/elf/testdata/gcc-amd64-linux-exec",
"debug/macho/testdata/gcc-386-darwin-exec.base64", // golang.org/issue/34986
"debug/macho/testdata/gcc-amd64-darwin-exec.base64", // golang.org/issue/34986
// "debug/pe/testdata/gcc-amd64-mingw-exec", // no symbols!
"debug/pe/testdata/gcc-386-mingw-exec",
"debug/plan9obj/testdata/amd64-plan9-exec",
"debug/plan9obj/testdata/386-plan9-exec",
"internal/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec",
}
for _, f := range testfiles {
exepath := filepath.Join(testenv.GOROOT(t), "src", f)
if strings.HasSuffix(f, ".base64") {
tf, err := obscuretestdata.DecodeToTempFile(exepath)
if err != nil {
t.Errorf("obscuretestdata.DecodeToTempFile(%s): %v", exepath, err)
continue
}
defer os.Remove(tf)
exepath = tf
}
cmd := exec.Command(testnmpath, exepath)
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("go tool nm %v: %v\n%s", exepath, err, string(out))
}
}
}
func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
t.Parallel()
tmpdir, err := os.MkdirTemp("", "TestGoExec")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "a.go")
file, err := os.Create(src)
if err != nil {
t.Fatal(err)
}
err = template.Must(template.New("main").Parse(testexec)).Execute(file, iscgo)
if e := file.Close(); err == nil {
err = e
}
if err != nil {
t.Fatal(err)
}
exe := filepath.Join(tmpdir, "a.exe")
args := []string{"build", "-o", exe}
if iscgo {
linkmode := "internal"
if isexternallinker {
linkmode = "external"
}
args = append(args, "-ldflags", "-linkmode="+linkmode)
}
args = append(args, src)
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
if err != nil {
t.Fatalf("building test executable failed: %s %s", err, out)
}
out, err = exec.Command(exe).CombinedOutput()
if err != nil {
t.Fatalf("running test executable failed: %s %s", err, out)
}
names := make(map[string]string)
for _, line := range strings.Split(string(out), "\n") {
if line == "" {
continue
}
f := strings.Split(line, "=")
if len(f) != 2 {
t.Fatalf("unexpected output line: %q", line)
}
names["main."+f[0]] = f[1]
}
runtimeSyms := map[string]string{
"runtime.text": "T",
"runtime.etext": "T",
"runtime.rodata": "R",
"runtime.erodata": "R",
"runtime.epclntab": "R",
"runtime.noptrdata": "D",
}
if runtime.GOOS == "aix" && iscgo {
// pclntab is moved to .data section on AIX.
runtimeSyms["runtime.epclntab"] = "D"
}
out, err = exec.Command(testnmpath, exe).CombinedOutput()
if err != nil {
t.Fatalf("go tool nm: %v\n%s", err, string(out))
}
relocated := func(code string) bool {
if runtime.GOOS == "aix" {
// On AIX, .data and .bss addresses are changed by the loader.
// Therefore, the values returned by the exec aren't the same
// than the ones inside the symbol table.
// In case of cgo, .text symbols are also changed.
switch code {
case "T", "t", "R", "r":
return iscgo
case "D", "d", "B", "b":
return true
}
}
if runtime.GOOS == "windows" {
return true
}
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
return true // On darwin/arm64 everything is PIE
}
return false
}
dups := make(map[string]bool)
for _, line := range strings.Split(string(out), "\n") {
f := strings.Fields(line)
if len(f) < 3 {
continue
}
name := f[2]
if addr, found := names[name]; found {
if want, have := addr, "0x"+f[0]; have != want {
if !relocated(f[1]) {
t.Errorf("want %s address for %s symbol, but have %s", want, name, have)
}
}
delete(names, name)
}
if _, found := dups[name]; found {
t.Errorf("duplicate name of %q is found", name)
}
if stype, found := runtimeSyms[name]; found {
if runtime.GOOS == "plan9" && stype == "R" {
// no read-only data segment symbol on Plan 9
stype = "D"
}
if want, have := stype, strings.ToUpper(f[1]); have != want {
t.Errorf("want %s type for %s symbol, but have %s", want, name, have)
}
delete(runtimeSyms, name)
}
}
if len(names) > 0 {
t.Errorf("executable is missing %v symbols", names)
}
if len(runtimeSyms) > 0 {
t.Errorf("executable is missing %v symbols", runtimeSyms)
}
}
func TestGoExec(t *testing.T) {
testGoExec(t, false, false)
}
func testGoLib(t *testing.T, iscgo bool) {
t.Parallel()
tmpdir, err := os.MkdirTemp("", "TestGoLib")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
gopath := filepath.Join(tmpdir, "gopath")
libpath := filepath.Join(gopath, "src", "mylib")
err = os.MkdirAll(libpath, 0777)
if err != nil {
t.Fatal(err)
}
src := filepath.Join(libpath, "a.go")
file, err := os.Create(src)
if err != nil {
t.Fatal(err)
}
err = template.Must(template.New("mylib").Parse(testlib)).Execute(file, iscgo)
if e := file.Close(); err == nil {
err = e
}
if err == nil {
err = os.WriteFile(filepath.Join(libpath, "go.mod"), []byte("module mylib\n"), 0666)
}
if err != nil {
t.Fatal(err)
}
cmd := exec.Command(testenv.GoToolPath(t), "build", "-buildmode=archive", "-o", "mylib.a", ".")
cmd.Dir = libpath
cmd.Env = append(os.Environ(), "GOPATH="+gopath)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("building test lib failed: %s %s", err, out)
}
mylib := filepath.Join(libpath, "mylib.a")
out, err = exec.Command(testnmpath, mylib).CombinedOutput()
if err != nil {
t.Fatalf("go tool nm: %v\n%s", err, string(out))
}
type symType struct {
Type string
Name string
CSym bool
Found bool
}
var syms = []symType{
{"B", "mylib.Testdata", false, false},
{"T", "mylib.Testfunc", false, false},
}
if iscgo {
syms = append(syms, symType{"B", "mylib.TestCgodata", false, false})
syms = append(syms, symType{"T", "mylib.TestCgofunc", false, false})
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" || (runtime.GOOS == "windows" && runtime.GOARCH == "386") {
syms = append(syms, symType{"D", "_cgodata", true, false})
syms = append(syms, symType{"T", "_cgofunc", true, false})
} else if runtime.GOOS == "aix" {
syms = append(syms, symType{"D", "cgodata", true, false})
syms = append(syms, symType{"T", ".cgofunc", true, false})
} else {
syms = append(syms, symType{"D", "cgodata", true, false})
syms = append(syms, symType{"T", "cgofunc", true, false})
}
}
for _, line := range strings.Split(string(out), "\n") {
f := strings.Fields(line)
var typ, name string
var csym bool
if iscgo {
if len(f) < 4 {
continue
}
csym = !strings.Contains(f[0], "_go_.o")
typ = f[2]
name = f[3]
} else {
if len(f) < 3 {
continue
}
typ = f[1]
name = f[2]
}
for i := range syms {
sym := &syms[i]
if sym.Type == typ && sym.Name == name && sym.CSym == csym {
if sym.Found {
t.Fatalf("duplicate symbol %s %s", sym.Type, sym.Name)
}
sym.Found = true
}
}
}
for _, sym := range syms {
if !sym.Found {
t.Errorf("cannot found symbol %s %s", sym.Type, sym.Name)
}
}
}
func TestGoLib(t *testing.T) {
testGoLib(t, false)
}
const testexec = `
package main
import "fmt"
{{if .}}import "C"
{{end}}
func main() {
testfunc()
}
var testdata uint32
func testfunc() {
fmt.Printf("main=%p\n", main)
fmt.Printf("testfunc=%p\n", testfunc)
fmt.Printf("testdata=%p\n", &testdata)
}
`
const testlib = `
package mylib
{{if .}}
// int cgodata = 5;
// void cgofunc(void) {}
import "C"
var TestCgodata = C.cgodata
func TestCgofunc() {
C.cgofunc()
}
{{end}}
var Testdata uint32
func Testfunc() {}
`
```
1.3.21 - objabi
1.3.22 - objdump
objdump
Overview
Objdump disassembles executable files.
Usage:
go tool objdump [-s symregexp] binary
Objdump prints a disassembly of all text symbols (code) in the binary. If the -s option is present, objdump only disassembles symbols with names matching the regular expression.
Alternate usage:
go tool objdump binary start end
In this mode, objdump disassembles the binary starting at the start address and stopping at the end address. The start and end addresses are program counters written in hexadecimal with optional leading 0x prefix. In this mode, objdump prints a sequence of stanzas of the form:
file:line
address: assembly
address: assembly
...
Each stanza gives the disassembly for a contiguous range of addresses all mapped to the same original source file and line number. This mode is intended for use by pprof.
=== “main.go”
``` go linenums="1"
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Objdump disassembles executable files.
//
// Usage:
//
// go tool objdump [-s symregexp] binary
//
// Objdump prints a disassembly of all text symbols (code) in the binary.
// If the -s option is present, objdump only disassembles
// symbols with names matching the regular expression.
//
// Alternate usage:
//
// go tool objdump binary start end
//
// In this mode, objdump disassembles the binary starting at the start address and
// stopping at the end address. The start and end addresses are program
// counters written in hexadecimal with optional leading 0x prefix.
// In this mode, objdump prints a sequence of stanzas of the form:
//
// file:line
// address: assembly
// address: assembly
// ...
//
// Each stanza gives the disassembly for a contiguous range of addresses
// all mapped to the same original source file and line number.
// This mode is intended for use by pprof.
package main
import (
"flag"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
"cmd/internal/objfile"
)
var printCode = flag.Bool("S", false, "print Go code alongside assembly")
var symregexp = flag.String("s", "", "only dump symbols matching this regexp")
var gnuAsm = flag.Bool("gnu", false, "print GNU assembly next to Go assembly (where supported)")
var symRE *regexp.Regexp
func usage() {
fmt.Fprintf(os.Stderr, "usage: go tool objdump [-S] [-gnu] [-s symregexp] binary [start end]\n\n")
flag.PrintDefaults()
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("objdump: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 && flag.NArg() != 3 {
usage()
}
if *symregexp != "" {
re, err := regexp.Compile(*symregexp)
if err != nil {
log.Fatalf("invalid -s regexp: %v", err)
}
symRE = re
}
f, err := objfile.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
defer f.Close()
dis, err := f.Disasm()
if err != nil {
log.Fatalf("disassemble %s: %v", flag.Arg(0), err)
}
switch flag.NArg() {
default:
usage()
case 1:
// disassembly of entire object
dis.Print(os.Stdout, symRE, 0, ^uint64(0), *printCode, *gnuAsm)
case 3:
// disassembly of PC range
start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64)
if err != nil {
log.Fatalf("invalid start PC: %v", err)
}
end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64)
if err != nil {
log.Fatalf("invalid end PC: %v", err)
}
dis.Print(os.Stdout, symRE, start, end, *printCode, *gnuAsm)
}
}
```
=== “objdump_test.go”
```go linenums="1"
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"cmd/internal/notsha256"
"flag"
"fmt"
"go/build"
"internal/testenv"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
var tmp, exe string // populated by buildObjdump
func TestMain(m *testing.M) {
if !testenv.HasGoBuild() {
return
}
var exitcode int
if err := buildObjdump(); err == nil {
exitcode = m.Run()
} else {
fmt.Println(err)
exitcode = 1
}
os.RemoveAll(tmp)
os.Exit(exitcode)
}
func buildObjdump() error {
var err error
tmp, err = os.MkdirTemp("", "TestObjDump")
if err != nil {
return fmt.Errorf("TempDir failed: %v", err)
}
exe = filepath.Join(tmp, "testobjdump.exe")
gotool, err := testenv.GoTool()
if err != nil {
return err
}
out, err := exec.Command(gotool, "build", "-o", exe, "cmd/objdump").CombinedOutput()
if err != nil {
os.RemoveAll(tmp)
return fmt.Errorf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out))
}
return nil
}
var x86Need = []string{ // for both 386 and AMD64
"JMP main.main(SB)",
"CALL main.Println(SB)",
"RET",
}
var amd64GnuNeed = []string{
"jmp",
"callq",
"cmpb",
}
var i386GnuNeed = []string{
"jmp",
"call",
"cmp",
}
var armNeed = []string{
"B main.main(SB)",
"BL main.Println(SB)",
"RET",
}
var arm64Need = []string{
"JMP main.main(SB)",
"CALL main.Println(SB)",
"RET",
}
var armGnuNeed = []string{ // for both ARM and AMR64
"ldr",
"bl",
"cmp",
}
var ppcNeed = []string{
"BR main.main(SB)",
"CALL main.Println(SB)",
"RET",
}
var ppcGnuNeed = []string{
"mflr",
"lbz",
"beq",
}
func mustHaveDisasm(t *testing.T) {
switch runtime.GOARCH {
case "loong64":
t.Skipf("skipping on %s", runtime.GOARCH)
case "mips", "mipsle", "mips64", "mips64le":
t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
case "riscv64":
t.Skipf("skipping on %s, issue 36738", runtime.GOARCH)
case "s390x":
t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
}
}
var target = flag.String("target", "", "test disassembly of `goos/goarch` binary")
// objdump is fully cross platform: it can handle binaries
// from any known operating system and architecture.
// We could in principle add binaries to testdata and check
// all the supported systems during this test. However, the
// binaries would be about 1 MB each, and we don't want to
// add that much junk to the hg repository. Instead, build a
// binary for the current system (only) and test that objdump
// can handle that one.
func testDisasm(t *testing.T, srcfname string, printCode bool, printGnuAsm bool, flags ...string) {
mustHaveDisasm(t)
goarch := runtime.GOARCH
if *target != "" {
f := strings.Split(*target, "/")
if len(f) != 2 {
t.Fatalf("-target argument must be goos/goarch")
}
defer os.Setenv("GOOS", os.Getenv("GOOS"))
defer os.Setenv("GOARCH", os.Getenv("GOARCH"))
os.Setenv("GOOS", f[0])
os.Setenv("GOARCH", f[1])
goarch = f[1]
}
hash := notsha256.Sum256([]byte(fmt.Sprintf("%v-%v-%v-%v", srcfname, flags, printCode, printGnuAsm)))
hello := filepath.Join(tmp, fmt.Sprintf("hello-%x.exe", hash))
args := []string{"build", "-o", hello}
args = append(args, flags...)
args = append(args, srcfname)
cmd := exec.Command(testenv.GoToolPath(t), args...)
// "Bad line" bug #36683 is sensitive to being run in the source directory.
cmd.Dir = "testdata"
// Ensure that the source file location embedded in the binary matches our
// actual current GOROOT, instead of GOROOT_FINAL if set.
cmd.Env = append(os.Environ(), "GOROOT_FINAL=")
t.Logf("Running %v", cmd.Args)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go build %s: %v\n%s", srcfname, err, out)
}
need := []string{
"TEXT main.main(SB)",
}
if printCode {
need = append(need, ` Println("hello, world")`)
} else {
need = append(need, srcfname+":6")
}
switch goarch {
case "amd64", "386":
need = append(need, x86Need...)
case "arm":
need = append(need, armNeed...)
case "arm64":
need = append(need, arm64Need...)
case "ppc64", "ppc64le":
need = append(need, ppcNeed...)
}
if printGnuAsm {
switch goarch {
case "amd64":
need = append(need, amd64GnuNeed...)
case "386":
need = append(need, i386GnuNeed...)
case "arm", "arm64":
need = append(need, armGnuNeed...)
case "ppc64", "ppc64le":
need = append(need, ppcGnuNeed...)
}
}
args = []string{
"-s", "main.main",
hello,
}
if printCode {
args = append([]string{"-S"}, args...)
}
if printGnuAsm {
args = append([]string{"-gnu"}, args...)
}
cmd = exec.Command(exe, args...)
cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory
out, err = cmd.CombinedOutput()
t.Logf("Running %v", cmd.Args)
if err != nil {
exename := srcfname[:len(srcfname)-len(filepath.Ext(srcfname))] + ".exe"
t.Fatalf("objdump %q: %v\n%s", exename, err, out)
}
text := string(out)
ok := true
for _, s := range need {
if !strings.Contains(text, s) {
t.Errorf("disassembly missing '%s'", s)
ok = false
}
}
if goarch == "386" {
if strings.Contains(text, "(IP)") {
t.Errorf("disassembly contains PC-Relative addressing on 386")
ok = false
}
}
if !ok || testing.Verbose() {
t.Logf("full disassembly:\n%s", text)
}
}
func testGoAndCgoDisasm(t *testing.T, printCode bool, printGnuAsm bool) {
t.Parallel()
testDisasm(t, "fmthello.go", printCode, printGnuAsm)
if build.Default.CgoEnabled {
testDisasm(t, "fmthellocgo.go", printCode, printGnuAsm)
}
}
func TestDisasm(t *testing.T) {
testGoAndCgoDisasm(t, false, false)
}
func TestDisasmCode(t *testing.T) {
testGoAndCgoDisasm(t, true, false)
}
func TestDisasmGnuAsm(t *testing.T) {
testGoAndCgoDisasm(t, false, true)
}
func TestDisasmExtld(t *testing.T) {
testenv.MustHaveCGO(t)
switch runtime.GOOS {
case "plan9", "windows":
t.Skipf("skipping on %s", runtime.GOOS)
}
t.Parallel()
testDisasm(t, "fmthello.go", false, false, "-ldflags=-linkmode=external")
}
func TestDisasmGoobj(t *testing.T) {
mustHaveDisasm(t)
hello := filepath.Join(tmp, "hello.o")
args := []string{"tool", "compile", "-p=main", "-o", hello}
args = append(args, "testdata/fmthello.go")
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
if err != nil {
t.Fatalf("go tool compile fmthello.go: %v\n%s", err, out)
}
need := []string{
"main(SB)",
"fmthello.go:6",
}
args = []string{
"-s", "main",
hello,
}
out, err = exec.Command(exe, args...).CombinedOutput()
if err != nil {
t.Fatalf("objdump fmthello.o: %v\n%s", err, out)
}
text := string(out)
ok := true
for _, s := range need {
if !strings.Contains(text, s) {
t.Errorf("disassembly missing '%s'", s)
ok = false
}
}
if runtime.GOARCH == "386" {
if strings.Contains(text, "(IP)") {
t.Errorf("disassembly contains PC-Relative addressing on 386")
ok = false
}
}
if !ok {
t.Logf("full disassembly:\n%s", text)
}
}
func TestGoobjFileNumber(t *testing.T) {
// Test that file table in Go object file is parsed correctly.
testenv.MustHaveGoBuild(t)
mustHaveDisasm(t)
t.Parallel()
tmpdir, err := os.MkdirTemp("", "TestGoobjFileNumber")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
obj := filepath.Join(tmpdir, "p.a")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", obj)
cmd.Dir = filepath.Join("testdata/testfilenum")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("build failed: %v\n%s", err, out)
}
cmd = exec.Command(exe, obj)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("objdump failed: %v\n%s", err, out)
}
text := string(out)
for _, s := range []string{"a.go", "b.go", "c.go"} {
if !strings.Contains(text, s) {
t.Errorf("output missing '%s'", s)
}
}
if t.Failed() {
t.Logf("output:\n%s", text)
}
}
func TestGoObjOtherVersion(t *testing.T) {
testenv.MustHaveExec(t)
t.Parallel()
obj := filepath.Join("testdata", "go116.o")
cmd := exec.Command(exe, obj)
out, err := cmd.CombinedOutput()
if err == nil {
t.Fatalf("objdump go116.o succeeded unexpectedly")
}
if !strings.Contains(string(out), "go object of a different version") {
t.Errorf("unexpected error message:\n%s", out)
}
}
```
1.3.23 - pack
pack
Overview 概述
pack是传统Unix ar工具的一个简单版本。它只实现Go所需的操作。
使用方法:
go tool pack op file.a [name...]
Pack applies the operation to the archive, using the names as arguments to the operation.
pack将操作应用于存档,使用名称(names )作为操作的参数。
The operation op is given by one of these letters:
操作op由下列字母中之一给出:
c append files (from the file system) to a new archive
=> 将文件(来自文件系统)追加到一个新的存档中
p print files from the archive
=> 打印存档中的文件
r append files (from the file system) to the archive
=> 将文件(从文件系统)追加到存档中
t list files from the archive
=> 列出存档中的文件
x extract files from the archive
=> 从存档中提取文件
c命令的存档参数必须是不存在的,或者是一个有效的(在添加新条目之前会被清除的)存档文件。如果文件存在但不是归档文件,则会是一个错误。
对于p、t和x命令,在命令行中不列出名称将导致操作应用于存档中的所有文件。
与Unix ar不同的是,r操作总是追加到归档文件中,即使归档文件中已经存在一个给定名称的文件。在这种情况下,pack的r操作更像Unix ar的rq操作。
在操作中添加字母v,如pv或rv,可以启用详细操作:
-
对于
c和r命令,在添加文件的时候会打印文件名。 -
对于
p命令,每个文件的前缀都是一行中单独的名称。 -
对于
t命令,列表中包括额外的文件元数据。 -
对于
x命令,在提取文件时打印名称。
=== “doc.go”
``` go linenums="1"
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Pack is a simple version of the traditional Unix ar tool.
It implements only the operations needed by Go.
Usage:
go tool pack op file.a [name...]
Pack applies the operation to the archive, using the names as arguments to the operation.
The operation op is given by one of these letters:
c append files (from the file system) to a new archive
p print files from the archive
r append files (from the file system) to the archive
t list files from the archive
x extract files from the archive
The archive argument to the c command must be non-existent or a
valid archive file, which will be cleared before adding new entries. It
is an error if the file exists but is not an archive.
For the p, t, and x commands, listing no names on the command line
causes the operation to apply to all files in the archive.
In contrast to Unix ar, the r operation always appends to the archive,
even if a file with the given name already exists in the archive. In this way
pack's r operation is more like Unix ar's rq operation.
Adding the letter v to an operation, as in pv or rv, enables verbose operation:
For the c and r commands, names are printed as files are added.
For the p command, each file is prefixed by the name on a line by itself.
For the t command, the listing includes additional file metadata.
For the x command, names are printed as files are extracted.
*/
```
=== “pack.go”
|
|
=== “pack_test.go”
```go linenums="1"
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bufio"
"bytes"
"cmd/internal/archive"
"fmt"
"internal/testenv"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
)
// testCreate creates an archive in the specified directory.
func testCreate(t *testing.T, dir string) {
name := filepath.Join(dir, "pack.a")
ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
// Add an entry by hand.
ar.addFile(helloFile.Reset())
ar.a.File().Close()
// Now check it.
ar = openArchive(name, os.O_RDONLY, []string{helloFile.name})
var buf bytes.Buffer
stdout = &buf
verbose = true
defer func() {
stdout = os.Stdout
verbose = false
}()
ar.scan(ar.printContents)
ar.a.File().Close()
result := buf.String()
// Expect verbose output plus file contents.
expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents)
if result != expect {
t.Fatalf("expected %q got %q", expect, result)
}
}
// Test that we can create an archive, write to it, and get the same contents back.
// Tests the rv and then the pv command on a new archive.
func TestCreate(t *testing.T) {
dir := t.TempDir()
testCreate(t, dir)
}
// Test that we can create an archive twice with the same name (Issue 8369).
func TestCreateTwice(t *testing.T) {
dir := t.TempDir()
testCreate(t, dir)
testCreate(t, dir)
}
// Test that we can create an archive, put some files in it, and get back a correct listing.
// Tests the tv command.
func TestTableOfContents(t *testing.T) {
dir := t.TempDir()
name := filepath.Join(dir, "pack.a")
ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
// Add some entries by hand.
ar.addFile(helloFile.Reset())
ar.addFile(goodbyeFile.Reset())
ar.a.File().Close()
// Now print it.
var buf bytes.Buffer
stdout = &buf
verbose = true
defer func() {
stdout = os.Stdout
verbose = false
}()
ar = openArchive(name, os.O_RDONLY, nil)
ar.scan(ar.tableOfContents)
ar.a.File().Close()
result := buf.String()
// Expect verbose listing.
expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry())
if result != expect {
t.Fatalf("expected %q got %q", expect, result)
}
// Do it again without verbose.
verbose = false
buf.Reset()
ar = openArchive(name, os.O_RDONLY, nil)
ar.scan(ar.tableOfContents)
ar.a.File().Close()
result = buf.String()
// Expect non-verbose listing.
expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name)
if result != expect {
t.Fatalf("expected %q got %q", expect, result)
}
// Do it again with file list arguments.
verbose = false
buf.Reset()
ar = openArchive(name, os.O_RDONLY, []string{helloFile.name})
ar.scan(ar.tableOfContents)
ar.a.File().Close()
result = buf.String()
// Expect only helloFile.
expect = fmt.Sprintf("%s\n", helloFile.name)
if result != expect {
t.Fatalf("expected %q got %q", expect, result)
}
}
// Test that we can create an archive, put some files in it, and get back a file.
// Tests the x command.
func TestExtract(t *testing.T) {
dir := t.TempDir()
name := filepath.Join(dir, "pack.a")
ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
// Add some entries by hand.
ar.addFile(helloFile.Reset())
ar.addFile(goodbyeFile.Reset())
ar.a.File().Close()
// Now extract one file. We chdir to the directory of the archive for simplicity.
pwd, err := os.Getwd()
if err != nil {
t.Fatal("os.Getwd: ", err)
}
err = os.Chdir(dir)
if err != nil {
t.Fatal("os.Chdir: ", err)
}
defer func() {
err := os.Chdir(pwd)
if err != nil {
t.Fatal("os.Chdir: ", err)
}
}()
ar = openArchive(name, os.O_RDONLY, []string{goodbyeFile.name})
ar.scan(ar.extractContents)
ar.a.File().Close()
data, err := os.ReadFile(goodbyeFile.name)
if err != nil {
t.Fatal(err)
}
// Expect contents of file.
result := string(data)
expect := goodbyeFile.contents
if result != expect {
t.Fatalf("expected %q got %q", expect, result)
}
}
// Test that pack-created archives can be understood by the tools.
func TestHello(t *testing.T) {
testenv.MustHaveGoBuild(t)
dir := t.TempDir()
hello := filepath.Join(dir, "hello.go")
prog := `
package main
func main() {
println("hello world")
}
`
err := os.WriteFile(hello, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
run := func(args ...string) string {
return doRun(t, dir, args...)
}
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
run(goBin, "tool", "compile", "-p=main", "hello.go")
run("./pack", "grc", "hello.a", "hello.o")
run(goBin, "tool", "link", "-o", "a.out", "hello.a")
out := run("./a.out")
if out != "hello world\n" {
t.Fatalf("incorrect output: %q, want %q", out, "hello world\n")
}
}
// Test that pack works with very long lines in PKGDEF.
func TestLargeDefs(t *testing.T) {
if testing.Short() {
t.Skip("skipping in -short mode")
}
testenv.MustHaveGoBuild(t)
dir := t.TempDir()
large := filepath.Join(dir, "large.go")
f, err := os.Create(large)
if err != nil {
t.Fatal(err)
}
b := bufio.NewWriter(f)
printf := func(format string, args ...any) {
_, err := fmt.Fprintf(b, format, args...)
if err != nil {
t.Fatalf("Writing to %s: %v", large, err)
}
}
printf("package large\n\ntype T struct {\n")
for i := 0; i < 1000; i++ {
printf("f%d int `tag:\"", i)
for j := 0; j < 100; j++ {
printf("t%d=%d,", j, j)
}
printf("\"`\n")
}
printf("}\n")
if err = b.Flush(); err != nil {
t.Fatal(err)
}
if err = f.Close(); err != nil {
t.Fatal(err)
}
main := filepath.Join(dir, "main.go")
prog := `
package main
import "large"
var V large.T
func main() {
println("ok")
}
`
err = os.WriteFile(main, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
run := func(args ...string) string {
return doRun(t, dir, args...)
}
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
run(goBin, "tool", "compile", "-p=large", "large.go")
run("./pack", "grc", "large.a", "large.o")
run(goBin, "tool", "compile", "-p=main", "-I", ".", "main.go")
run(goBin, "tool", "link", "-L", ".", "-o", "a.out", "main.o")
out := run("./a.out")
if out != "ok\n" {
t.Fatalf("incorrect output: %q, want %q", out, "ok\n")
}
}
// Test that "\n!\n" inside export data doesn't result in a truncated
// package definition when creating a .a archive from a .o Go object.
func TestIssue21703(t *testing.T) {
testenv.MustHaveGoBuild(t)
dir := t.TempDir()
const aSrc = `package a; const X = "\n!\n"`
err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666)
if err != nil {
t.Fatal(err)
}
const bSrc = `package b; import _ "a"`
err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666)
if err != nil {
t.Fatal(err)
}
run := func(args ...string) string {
return doRun(t, dir, args...)
}
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
run(goBin, "tool", "compile", "-p=a", "a.go")
run("./pack", "c", "a.a", "a.o")
run(goBin, "tool", "compile", "-p=b", "-I", ".", "b.go")
}
// Test the "c" command can "see through" the archive generated by the compiler.
// This is peculiar. (See issue #43271)
func TestCreateWithCompilerObj(t *testing.T) {
testenv.MustHaveGoBuild(t)
dir := t.TempDir()
src := filepath.Join(dir, "p.go")
prog := "package p; var X = 42\n"
err := os.WriteFile(src, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
run := func(args ...string) string {
return doRun(t, dir, args...)
}
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
run(goBin, "tool", "compile", "-pack", "-p=p", "-o", "p.a", "p.go")
run("./pack", "c", "packed.a", "p.a")
fi, err := os.Stat(filepath.Join(dir, "p.a"))
if err != nil {
t.Fatalf("stat p.a failed: %v", err)
}
fi2, err := os.Stat(filepath.Join(dir, "packed.a"))
if err != nil {
t.Fatalf("stat packed.a failed: %v", err)
}
// For compiler-generated object file, the "c" command is
// expected to get (essentially) the same file back, instead
// of packing it into a new archive with a single entry.
if want, got := fi.Size(), fi2.Size(); want != got {
t.Errorf("packed file with different size: want %d, got %d", want, got)
}
// Test -linkobj flag as well.
run(goBin, "tool", "compile", "-p=p", "-linkobj", "p2.a", "-o", "p.x", "p.go")
run("./pack", "c", "packed2.a", "p2.a")
fi, err = os.Stat(filepath.Join(dir, "p2.a"))
if err != nil {
t.Fatalf("stat p2.a failed: %v", err)
}
fi2, err = os.Stat(filepath.Join(dir, "packed2.a"))
if err != nil {
t.Fatalf("stat packed2.a failed: %v", err)
}
if want, got := fi.Size(), fi2.Size(); want != got {
t.Errorf("packed file with different size: want %d, got %d", want, got)
}
run("./pack", "c", "packed3.a", "p.x")
fi, err = os.Stat(filepath.Join(dir, "p.x"))
if err != nil {
t.Fatalf("stat p.x failed: %v", err)
}
fi2, err = os.Stat(filepath.Join(dir, "packed3.a"))
if err != nil {
t.Fatalf("stat packed3.a failed: %v", err)
}
if want, got := fi.Size(), fi2.Size(); want != got {
t.Errorf("packed file with different size: want %d, got %d", want, got)
}
}
// Test the "r" command creates the output file if it does not exist.
func TestRWithNonexistentFile(t *testing.T) {
testenv.MustHaveGoBuild(t)
dir := t.TempDir()
src := filepath.Join(dir, "p.go")
prog := "package p; var X = 42\n"
err := os.WriteFile(src, []byte(prog), 0666)
if err != nil {
t.Fatal(err)
}
run := func(args ...string) string {
return doRun(t, dir, args...)
}
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
run(goBin, "tool", "compile", "-p=p", "-o", "p.o", "p.go")
run("./pack", "r", "p.a", "p.o") // should succeed
}
// doRun runs a program in a directory and returns the output.
func doRun(t *testing.T, dir string, args ...string) string {
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("%v: %v\n%s", args, err, string(out))
}
return string(out)
}
// Fake implementation of files.
var helloFile = &FakeFile{
name: "hello",
contents: "hello world", // 11 bytes, an odd number.
mode: 0644,
}
var goodbyeFile = &FakeFile{
name: "goodbye",
contents: "Sayonara, Jim", // 13 bytes, another odd number.
mode: 0644,
}
// FakeFile implements FileLike and also fs.FileInfo.
type FakeFile struct {
name string
contents string
mode fs.FileMode
offset int
}
// Reset prepares a FakeFile for reuse.
func (f *FakeFile) Reset() *FakeFile {
f.offset = 0
return f
}
// FileLike methods.
func (f *FakeFile) Name() string {
// A bit of a cheat: we only have a basename, so that's also ok for FileInfo.
return f.name
}
func (f *FakeFile) Stat() (fs.FileInfo, error) {
return f, nil
}
func (f *FakeFile) Read(p []byte) (int, error) {
if f.offset >= len(f.contents) {
return 0, io.EOF
}
n := copy(p, f.contents[f.offset:])
f.offset += n
return n, nil
}
func (f *FakeFile) Close() error {
return nil
}
// fs.FileInfo methods.
func (f *FakeFile) Size() int64 {
return int64(len(f.contents))
}
func (f *FakeFile) Mode() fs.FileMode {
return f.mode
}
func (f *FakeFile) ModTime() time.Time {
return time.Time{}
}
func (f *FakeFile) IsDir() bool {
return false
}
func (f *FakeFile) Sys() any {
return nil
}
// Special helpers.
func (f *FakeFile) Entry() *archive.Entry {
return &archive.Entry{
Name: f.name,
Mtime: 0, // Defined to be zero.
Uid: 0, // Ditto.
Gid: 0, // Ditto.
Mode: f.mode,
Data: archive.Data{Size: int64(len(f.contents))},
}
}
```
1.3.24 - pprof
pprof
Overview 概述
pprof 解释(interprets )并显示(displays )Go程序的配置文件。
基本用法:
go tool pprof binary profile
详细使用信息:
go tool pprof -h
举个例子,见https://blog.golang.org/profiling-go-programs。
=== “pprof.go”
```go linenums="1"
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// pprof is a tool for visualization of profile.data. It is based on
// the upstream version at github.com/google/pprof, with minor
// modifications specific to the Go distribution. Please consider
// upstreaming any modifications to these packages.
package main
import (
"crypto/tls"
"debug/dwarf"
"fmt"
"io"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"sync"
"time"
"cmd/internal/objfile"
"github.com/google/pprof/driver"
"github.com/google/pprof/profile"
)
func main() {
options := &driver.Options{
Fetch: new(fetcher),
Obj: new(objTool),
UI: newUI(),
}
if err := driver.PProf(options); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(2)
}
}
type fetcher struct {
}
func (f *fetcher) Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error) {
sourceURL, timeout := adjustURL(src, duration, timeout)
if sourceURL == "" {
// Could not recognize URL, let regular pprof attempt to fetch the profile (eg. from a file)
return nil, "", nil
}
fmt.Fprintln(os.Stderr, "Fetching profile over HTTP from", sourceURL)
if duration > 0 {
fmt.Fprintf(os.Stderr, "Please wait... (%v)\n", duration)
}
p, err := getProfile(sourceURL, timeout)
return p, sourceURL, err
}
func getProfile(source string, timeout time.Duration) (*profile.Profile, error) {
url, err := url.Parse(source)
if err != nil {
return nil, err
}
var tlsConfig *tls.Config
if url.Scheme == "https+insecure" {
tlsConfig = &tls.Config{
InsecureSkipVerify: true,
}
url.Scheme = "https"
source = url.String()
}
client := &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: timeout + 5*time.Second,
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: tlsConfig,
},
}
resp, err := client.Get(source)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
defer resp.Body.Close()
return nil, statusCodeError(resp)
}
return profile.Parse(resp.Body)
}
func statusCodeError(resp *http.Response) error {
if resp.Header.Get("X-Go-Pprof") != "" && strings.Contains(resp.Header.Get("Content-Type"), "text/plain") {
// error is from pprof endpoint
if body, err := io.ReadAll(resp.Body); err == nil {
return fmt.Errorf("server response: %s - %s", resp.Status, body)
}
}
return fmt.Errorf("server response: %s", resp.Status)
}
// cpuProfileHandler is the Go pprof CPU profile handler URL.
const cpuProfileHandler = "/debug/pprof/profile"
// adjustURL applies the duration/timeout values and Go specific defaults
func adjustURL(source string, duration, timeout time.Duration) (string, time.Duration) {
u, err := url.Parse(source)
if err != nil || (u.Host == "" && u.Scheme != "" && u.Scheme != "file") {
// Try adding http:// to catch sources of the form hostname:port/path.
// url.Parse treats "hostname" as the scheme.
u, err = url.Parse("http://" + source)
}
if err != nil || u.Host == "" {
return "", 0
}
if u.Path == "" || u.Path == "/" {
u.Path = cpuProfileHandler
}
// Apply duration/timeout overrides to URL.
values := u.Query()
if duration > 0 {
values.Set("seconds", fmt.Sprint(int(duration.Seconds())))
} else {
if urlSeconds := values.Get("seconds"); urlSeconds != "" {
if us, err := strconv.ParseInt(urlSeconds, 10, 32); err == nil {
duration = time.Duration(us) * time.Second
}
}
}
if timeout <= 0 {
if duration > 0 {
timeout = duration + duration/2
} else {
timeout = 60 * time.Second
}
}
u.RawQuery = values.Encode()
return u.String(), timeout
}
// objTool implements driver.ObjTool using Go libraries
// (instead of invoking GNU binutils).
type objTool struct {
mu sync.Mutex
disasmCache map[string]*objfile.Disasm
}
func (*objTool) Open(name string, start, limit, offset uint64, relocationSymbol string) (driver.ObjFile, error) {
of, err := objfile.Open(name)
if err != nil {
return nil, err
}
f := &file{
name: name,
file: of,
}
if start != 0 {
if load, err := of.LoadAddress(); err == nil {
f.offset = start - load
}
}
return f, nil
}
func (*objTool) Demangle(names []string) (map[string]string, error) {
// No C++, nothing to demangle.
return make(map[string]string), nil
}
func (t *objTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]driver.Inst, error) {
if intelSyntax {
return nil, fmt.Errorf("printing assembly in Intel syntax is not supported")
}
d, err := t.cachedDisasm(file)
if err != nil {
return nil, err
}
var asm []driver.Inst
d.Decode(start, end, nil, false, func(pc, size uint64, file string, line int, text string) {
asm = append(asm, driver.Inst{Addr: pc, File: file, Line: line, Text: text})
})
return asm, nil
}
func (t *objTool) cachedDisasm(file string) (*objfile.Disasm, error) {
t.mu.Lock()
defer t.mu.Unlock()
if t.disasmCache == nil {
t.disasmCache = make(map[string]*objfile.Disasm)
}
d := t.disasmCache[file]
if d != nil {
return d, nil
}
f, err := objfile.Open(file)
if err != nil {
return nil, err
}
d, err = f.Disasm()
f.Close()
if err != nil {
return nil, err
}
t.disasmCache[file] = d
return d, nil
}
func (*objTool) SetConfig(config string) {
// config is usually used to say what binaries to invoke.
// Ignore entirely.
}
// file implements driver.ObjFile using Go libraries
// (instead of invoking GNU binutils).
// A file represents a single executable being analyzed.
type file struct {
name string
offset uint64
sym []objfile.Sym
file *objfile.File
pcln objfile.Liner
triedDwarf bool
dwarf *dwarf.Data
}
func (f *file) Name() string {
return f.name
}
func (f *file) ObjAddr(addr uint64) (uint64, error) {
// No support for shared libraries, so translation is a no-op.
return addr, nil
}
func (f *file) BuildID() string {
// No support for build ID.
return ""
}
func (f *file) SourceLine(addr uint64) ([]driver.Frame, error) {
if f.pcln == nil {
pcln, err := f.file.PCLineTable()
if err != nil {
return nil, err
}
f.pcln = pcln
}
addr -= f.offset
file, line, fn := f.pcln.PCToLine(addr)
if fn != nil {
frame := []driver.Frame{
{
Func: fn.Name,
File: file,
Line: line,
},
}
return frame, nil
}
frames := f.dwarfSourceLine(addr)
if frames != nil {
return frames, nil
}
return nil, fmt.Errorf("no line information for PC=%#x", addr)
}
// dwarfSourceLine tries to get file/line information using DWARF.
// This is for C functions that appear in the profile.
// Returns nil if there is no information available.
func (f *file) dwarfSourceLine(addr uint64) []driver.Frame {
if f.dwarf == nil && !f.triedDwarf {
// Ignore any error--we don't care exactly why there
// is no DWARF info.
f.dwarf, _ = f.file.DWARF()
f.triedDwarf = true
}
if f.dwarf != nil {
r := f.dwarf.Reader()
unit, err := r.SeekPC(addr)
if err == nil {
if frames := f.dwarfSourceLineEntry(r, unit, addr); frames != nil {
return frames
}
}
}
return nil
}
// dwarfSourceLineEntry tries to get file/line information from a
// DWARF compilation unit. Returns nil if it doesn't find anything.
func (f *file) dwarfSourceLineEntry(r *dwarf.Reader, entry *dwarf.Entry, addr uint64) []driver.Frame {
lines, err := f.dwarf.LineReader(entry)
if err != nil {
return nil
}
var lentry dwarf.LineEntry
if err := lines.SeekPC(addr, &lentry); err != nil {
return nil
}
// Try to find the function name.
name := ""
FindName:
for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() {
if entry.Tag == dwarf.TagSubprogram {
ranges, err := f.dwarf.Ranges(entry)
if err != nil {
return nil
}
for _, pcs := range ranges {
if pcs[0] <= addr && addr < pcs[1] {
var ok bool
// TODO: AT_linkage_name, AT_MIPS_linkage_name.
name, ok = entry.Val(dwarf.AttrName).(string)
if ok {
break FindName
}
}
}
}
}
// TODO: Report inlined functions.
frames := []driver.Frame{
{
Func: name,
File: lentry.File.Name,
Line: lentry.Line,
},
}
return frames
}
func (f *file) Symbols(r *regexp.Regexp, addr uint64) ([]*driver.Sym, error) {
if f.sym == nil {
sym, err := f.file.Symbols()
if err != nil {
return nil, err
}
f.sym = sym
}
var out []*driver.Sym
for _, s := range f.sym {
// Ignore a symbol with address 0 and size 0.
// An ELF STT_FILE symbol will look like that.
if s.Addr == 0 && s.Size == 0 {
continue
}
if (r == nil || r.MatchString(s.Name)) && (addr == 0 || s.Addr <= addr && addr < s.Addr+uint64(s.Size)) {
out = append(out, &driver.Sym{
Name: []string{s.Name},
File: f.name,
Start: s.Addr,
End: s.Addr + uint64(s.Size) - 1,
})
}
}
return out, nil
}
func (f *file) Close() error {
f.file.Close()
return nil
}
// newUI will be set in readlineui.go in some platforms
// for interactive readline functionality.
var newUI = func() driver.UI { return nil }
```
=== “pprof_test.go”
```go linenums="1"
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"internal/testenv"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
var tmp, pprofExe string // populated by buildPprof
func TestMain(m *testing.M) {
if !testenv.HasGoBuild() {
return
}
var exitcode int
if err := buildPprof(); err == nil {
exitcode = m.Run()
} else {
fmt.Println(err)
exitcode = 1
}
os.RemoveAll(tmp)
os.Exit(exitcode)
}
func buildPprof() error {
var err error
tmp, err = os.MkdirTemp("", "TestPprof")
if err != nil {
return fmt.Errorf("TempDir failed: %v", err)
}
pprofExe = filepath.Join(tmp, "testpprof.exe")
gotool, err := testenv.GoTool()
if err != nil {
return err
}
out, err := exec.Command(gotool, "build", "-o", pprofExe, "cmd/pprof").CombinedOutput()
if err != nil {
os.RemoveAll(tmp)
return fmt.Errorf("go build -o %v cmd/pprof: %v\n%s", pprofExe, err, string(out))
}
return nil
}
// See also runtime/pprof.cpuProfilingBroken.
func mustHaveCPUProfiling(t *testing.T) {
switch runtime.GOOS {
case "plan9":
t.Skipf("skipping on %s, unimplemented", runtime.GOOS)
case "aix":
t.Skipf("skipping on %s, issue 45170", runtime.GOOS)
case "ios", "dragonfly", "netbsd", "illumos", "solaris":
t.Skipf("skipping on %s, issue 13841", runtime.GOOS)
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
t.Skipf("skipping on %s/%s, issue 13841", runtime.GOOS, runtime.GOARCH)
}
}
}
func mustHaveDisasm(t *testing.T) {
switch runtime.GOARCH {
case "loong64":
t.Skipf("skipping on %s.", runtime.GOARCH)
case "mips", "mipsle", "mips64", "mips64le":
t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
case "riscv64":
t.Skipf("skipping on %s, issue 36738", runtime.GOARCH)
case "s390x":
t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
}
// Skip PIE platforms, pprof can't disassemble PIE.
if runtime.GOOS == "windows" {
t.Skipf("skipping on %s, issue 46639", runtime.GOOS)
}
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
t.Skipf("skipping on %s/%s, issue 46639", runtime.GOOS, runtime.GOARCH)
}
}
// TestDisasm verifies that cmd/pprof can successfully disassemble functions.
//
// This is a regression test for issue 46636.
func TestDisasm(t *testing.T) {
mustHaveCPUProfiling(t)
mustHaveDisasm(t)
testenv.MustHaveGoBuild(t)
tmpdir := t.TempDir()
cpuExe := filepath.Join(tmpdir, "cpu.exe")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", cpuExe, "cpu.go")
cmd.Dir = "testdata/"
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("build failed: %v\n%s", err, out)
}
profile := filepath.Join(tmpdir, "cpu.pprof")
cmd = exec.Command(cpuExe, "-output", profile)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("cpu failed: %v\n%s", err, out)
}
cmd = exec.Command(pprofExe, "-disasm", "main.main", cpuExe, profile)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("pprof failed: %v\n%s", err, out)
}
sout := string(out)
want := "ROUTINE ======================== main.main"
if !strings.Contains(sout, want) {
t.Errorf("pprof disasm got %s want contains %q", sout, want)
}
}
```
1.3.25 - test2json
test2json
Overview
Test2json converts go test output to a machine-readable JSON stream.
Usage:
go tool test2json [-p pkg] [-t] [./pkg.test -test.v [-test.paniconexit0]]
Test2json runs the given test command and converts its output to JSON; with no command specified, test2json expects test output on standard input. It writes a corresponding stream of JSON events to standard output. There is no unnecessary input or output buffering, so that the JSON stream can be read for “live updates” of test status.
The -p flag sets the package reported in each test event.
The -t flag requests that time stamps be added to each test event.
The test must be invoked with -test.v. Additionally passing -test.paniconexit0 will cause test2json to exit with a non-zero status if one of the tests being run calls os.Exit(0).
Note that test2json is only intended for converting a single test binary’s output. To convert the output of a “go test” command, use “go test -json” instead of invoking test2json directly.
Output Format
The JSON stream is a newline-separated sequence of TestEvent objects corresponding to the Go struct:
type TestEvent struct {
Time time.Time // encodes as an RFC3339-format string
Action string
Package string
Test string
Elapsed float64 // seconds
Output string
}
The Time field holds the time the event happened. It is conventionally omitted for cached test results.
The Action field is one of a fixed set of action descriptions:
run - the test has started running
pause - the test has been paused
cont - the test has continued running
pass - the test passed
bench - the benchmark printed log output but did not fail
fail - the test or benchmark failed
output - the test printed output
skip - the test was skipped or the package contained no tests
The Package field, if present, specifies the package being tested. When the go command runs parallel tests in -json mode, events from different tests are interlaced; the Package field allows readers to separate them.
The Test field, if present, specifies the test, example, or benchmark function that caused the event. Events for the overall package test do not set Test.
The Elapsed field is set for “pass” and “fail” events. It gives the time elapsed for the specific test or the overall package test that passed or failed.
The Output field is set for Action == “output” and is a portion of the test’s output (standard output and standard error merged together). The output is unmodified except that invalid UTF-8 output from a test is coerced into valid UTF-8 by use of replacement characters. With that one exception, the concatenation of the Output fields of all output events is the exact output of the test execution.
When a benchmark runs, it typically produces a single line of output giving timing results. That line is reported in an event with Action == “output” and no Test field. If a benchmark logs output or reports a failure (for example, by using b.Log or b.Error), that extra output is reported as a sequence of events with Test set to the benchmark name, terminated by a final event with Action == “bench” or “fail”. Benchmarks have no events with Action == “run”, “pause”, or “cont”.
=== “main.go”
``` go linenums="1"
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test2json converts go test output to a machine-readable JSON stream.
//
// Usage:
//
// go tool test2json [-p pkg] [-t] [./pkg.test -test.v [-test.paniconexit0]]
//
// Test2json runs the given test command and converts its output to JSON;
// with no command specified, test2json expects test output on standard input.
// It writes a corresponding stream of JSON events to standard output.
// There is no unnecessary input or output buffering, so that
// the JSON stream can be read for “live updates” of test status.
//
// The -p flag sets the package reported in each test event.
//
// The -t flag requests that time stamps be added to each test event.
//
// The test must be invoked with -test.v. Additionally passing
// -test.paniconexit0 will cause test2json to exit with a non-zero
// status if one of the tests being run calls os.Exit(0).
//
// Note that test2json is only intended for converting a single test
// binary's output. To convert the output of a "go test" command,
// use "go test -json" instead of invoking test2json directly.
//
// # Output Format
//
// The JSON stream is a newline-separated sequence of TestEvent objects
// corresponding to the Go struct:
//
// type TestEvent struct {
// Time time.Time // encodes as an RFC3339-format string
// Action string
// Package string
// Test string
// Elapsed float64 // seconds
// Output string
// }
//
// The Time field holds the time the event happened.
// It is conventionally omitted for cached test results.
//
// The Action field is one of a fixed set of action descriptions:
//
// run - the test has started running
// pause - the test has been paused
// cont - the test has continued running
// pass - the test passed
// bench - the benchmark printed log output but did not fail
// fail - the test or benchmark failed
// output - the test printed output
// skip - the test was skipped or the package contained no tests
//
// The Package field, if present, specifies the package being tested.
// When the go command runs parallel tests in -json mode, events from
// different tests are interlaced; the Package field allows readers to
// separate them.
//
// The Test field, if present, specifies the test, example, or benchmark
// function that caused the event. Events for the overall package test
// do not set Test.
//
// The Elapsed field is set for "pass" and "fail" events. It gives the time
// elapsed for the specific test or the overall package test that passed or failed.
//
// The Output field is set for Action == "output" and is a portion of the test's output
// (standard output and standard error merged together). The output is
// unmodified except that invalid UTF-8 output from a test is coerced
// into valid UTF-8 by use of replacement characters. With that one exception,
// the concatenation of the Output fields of all output events is the exact
// output of the test execution.
//
// When a benchmark runs, it typically produces a single line of output
// giving timing results. That line is reported in an event with Action == "output"
// and no Test field. If a benchmark logs output or reports a failure
// (for example, by using b.Log or b.Error), that extra output is reported
// as a sequence of events with Test set to the benchmark name, terminated
// by a final event with Action == "bench" or "fail".
// Benchmarks have no events with Action == "run", "pause", or "cont".
package main
import (
"flag"
"fmt"
"io"
"os"
"os/exec"
"cmd/internal/test2json"
)
var (
flagP = flag.String("p", "", "report `pkg` as the package being tested in each event")
flagT = flag.Bool("t", false, "include timestamps in events")
)
func usage() {
fmt.Fprintf(os.Stderr, "usage: go tool test2json [-p pkg] [-t] [./pkg.test -test.v]\n")
os.Exit(2)
}
func main() {
flag.Usage = usage
flag.Parse()
var mode test2json.Mode
if *flagT {
mode |= test2json.Timestamp
}
c := test2json.NewConverter(os.Stdout, *flagP, mode)
defer c.Close()
if flag.NArg() == 0 {
io.Copy(c, os.Stdin)
} else {
args := flag.Args()
cmd := exec.Command(args[0], args[1:]...)
w := &countWriter{0, c}
cmd.Stdout = w
cmd.Stderr = w
err := cmd.Run()
if err != nil {
if w.n > 0 {
// Assume command printed why it failed.
} else {
fmt.Fprintf(c, "test2json: %v\n", err)
}
}
c.Exited(err)
if err != nil {
c.Close()
os.Exit(1)
}
}
}
type countWriter struct {
n int64
w io.Writer
}
func (w *countWriter) Write(b []byte) (int, error) {
w.n += int64(len(b))
return w.w.Write(b)
}
```
1.3.26 - trace
trace
Overview 概述
Trace is a tool for viewing trace files.
Trace是一个查看跟踪文件的工具。
Trace files can be generated with:
跟踪文件可以通过以下方式生成:
-
runtime/trace.Start
-
net/http/pprof package
-
go test -trace
Example usage: Generate a trace file with ‘go test’:
使用实例。用’go test’生成一个跟踪文件:
go test -trace trace.out pkg
View the trace in a web browser:
在网络浏览器中查看跟踪:
go tool trace trace.out
Generate a pprof-like profile from the trace:
从跟踪中生成一个类似于pprof的配置文件:
go tool trace -pprof=TYPE trace.out > TYPE.pprof
Supported profile types are:
支持的配置文件类型有:
- net: network blocking profile
- sync: synchronization blocking profile
- syscall: syscall blocking profile
- sched: scheduler latency profile
- net:网络阻断配置文件 sync:同步阻断配置文件 syscall:系统调用阻塞配置文件 sched:调度器延迟配置文件
Then, you can use the pprof tool to analyze the profile:
然后,你可以使用pprof工具来分析配置文件:
go tool pprof TYPE.pprof
Note that while the various profiles available when launching ‘go tool trace’ work on every browser, the trace viewer itself (the ‘view trace’ page) comes from the Chrome/Chromium project and is only actively tested on that browser.
请注意,虽然启动 “go tool trace “时可用的各种配置文件在每个浏览器上都能工作,但跟踪查看器本身(“查看跟踪 “页面)来自Chrome/Chromium项目,并且只在该浏览器上积极测试。
1.3.27 - vet
vet
Overview 概述
Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string. Vet uses heuristics that do not guarantee all reports are genuine problems, but it can find errors not caught by the compilers.
Vet检查Go源代码并报告可疑的结构,例如参数与格式字符串不一致的Printf调用。Vet使用启发式方法,不能保证所有报告都是真正的问题,但它可以发现编译器没有发现的错误。
Vet is normally invoked through the go command. This command vets the package in the current directory:
Vet通常是通过go命令调用的。该命令对当前目录下的软件包进行审查:
go vet
whereas this one vets the packages whose path is provided:
而这个命令是对提供了路径的软件包进行审查:
go vet my/project/...
Use “go help packages” to see other ways of specifying which packages to vet.
使用 “go help packages “来查看其他指定审查软件包的方法。
Vet’s exit code is non-zero for erroneous invocation of the tool or if a problem was reported, and 0 otherwise. Note that the tool does not check every possible problem and depends on unreliable heuristics, so it should be used as guidance only, not as a firm indicator of program correctness.
Vet的退出代码在错误地调用工具或报告问题时为非零,否则为0。请注意,该工具并没有检查每一个可能的问题,而是依赖于不可靠的启发式方法,所以它应该只作为指导,而不是作为程序正确性的一个确定指标。
To list the available checks, run “go tool vet help”:
要列出可用的检查,请运行 “go tool vet help”:
asmdecl report mismatches between assembly files and Go declarations
assign check for useless assignments
atomic check for common mistakes using the sync/atomic package
bools check for common mistakes involving boolean operators
buildtag check that +build tags are well-formed and correctly located
cgocall detect some violations of the cgo pointer passing rules
composites check for unkeyed composite literals
copylocks check for locks erroneously passed by value
httpresponse check for mistakes using HTTP responses
loopclosure check references to loop variables from within nested functions
lostcancel check cancel func returned by context.WithCancel is called
nilfunc check for useless comparisons between functions and nil
printf check consistency of Printf format strings and arguments
shift check for shifts that equal or exceed the width of the integer
stdmethods check signature of methods of well-known interfaces
structtag check that struct field tags conform to reflect.StructTag.Get
tests check for common mistaken usages of tests and examples
unmarshal report passing non-pointer or non-interface values to unmarshal
unreachable check for unreachable code
unsafeptr check for invalid conversions of uintptr to unsafe.Pointer
unusedresult check for unused results of calls to some functions
For details and flags of a particular check, such as printf, run “go tool vet help printf”.
要了解某个特定检查的细节和标志,例如printf,请运行 “go tool vet help printf”。
By default, all checks are performed. If any flags are explicitly set to true, only those tests are run. Conversely, if any flag is explicitly set to false, only those tests are disabled. Thus -printf=true runs the printf check, and -printf=false runs all checks except the printf check.
默认情况下,所有的检查都被执行。如果任何标志被明确地设置为 “true”,则只有这些测试被运行。反之,如果任何标志被明确设置为false,则只有这些测试被禁用。因此,-printf=true运行printf检查,而-printf=false运行除printf检查之外的所有检查。
For information on writing a new check, see golang.org/x/tools/go/analysis.
有关编写新检查的信息,请参见golang.org/x/tools/go/analysis。
Core flags:
核心标志:
-c=N
display offending line plus N lines of surrounding context
-json
emit analysis diagnostics (and errors) in JSON format
=== “main.go”
```go linenums="1"
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"cmd/internal/objabi"
"golang.org/x/tools/go/analysis/unitchecker"
"golang.org/x/tools/go/analysis/passes/asmdecl"
"golang.org/x/tools/go/analysis/passes/assign"
"golang.org/x/tools/go/analysis/passes/atomic"
"golang.org/x/tools/go/analysis/passes/bools"
"golang.org/x/tools/go/analysis/passes/buildtag"
"golang.org/x/tools/go/analysis/passes/cgocall"
"golang.org/x/tools/go/analysis/passes/composite"
"golang.org/x/tools/go/analysis/passes/copylock"
"golang.org/x/tools/go/analysis/passes/errorsas"
"golang.org/x/tools/go/analysis/passes/framepointer"
"golang.org/x/tools/go/analysis/passes/httpresponse"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/go/analysis/passes/lostcancel"
"golang.org/x/tools/go/analysis/passes/nilfunc"
"golang.org/x/tools/go/analysis/passes/printf"
"golang.org/x/tools/go/analysis/passes/shift"
"golang.org/x/tools/go/analysis/passes/sigchanyzer"
"golang.org/x/tools/go/analysis/passes/stdmethods"
"golang.org/x/tools/go/analysis/passes/stringintconv"
"golang.org/x/tools/go/analysis/passes/structtag"
"golang.org/x/tools/go/analysis/passes/testinggoroutine"
"golang.org/x/tools/go/analysis/passes/tests"
"golang.org/x/tools/go/analysis/passes/unmarshal"
"golang.org/x/tools/go/analysis/passes/unreachable"
"golang.org/x/tools/go/analysis/passes/unsafeptr"
"golang.org/x/tools/go/analysis/passes/unusedresult"
)
func main() {
objabi.AddVersionFlag()
unitchecker.Main(
asmdecl.Analyzer,
assign.Analyzer,
atomic.Analyzer,
bools.Analyzer,
buildtag.Analyzer,
cgocall.Analyzer,
composite.Analyzer,
copylock.Analyzer,
errorsas.Analyzer,
framepointer.Analyzer,
httpresponse.Analyzer,
ifaceassert.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
printf.Analyzer,
shift.Analyzer,
sigchanyzer.Analyzer,
stdmethods.Analyzer,
stringintconv.Analyzer,
structtag.Analyzer,
tests.Analyzer,
testinggoroutine.Analyzer,
unmarshal.Analyzer,
unreachable.Analyzer,
unsafeptr.Analyzer,
unusedresult.Analyzer,
)
}
```
=== “vet_test.go”
```go linenums="1"
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main_test
import (
"bytes"
"errors"
"fmt"
"internal/testenv"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
"testing"
)
const dataDir = "testdata"
var binary string
// We implement TestMain so remove the test binary when all is done.
func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
func testMain(m *testing.M) int {
dir, err := os.MkdirTemp("", "vet_test")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return 1
}
defer os.RemoveAll(dir)
binary = filepath.Join(dir, "testvet.exe")
return m.Run()
}
var (
buildMu sync.Mutex // guards following
built = false // We have built the binary.
failed = false // We have failed to build the binary, don't try again.
)
func Build(t *testing.T) {
buildMu.Lock()
defer buildMu.Unlock()
if built {
return
}
if failed {
t.Skip("cannot run on this environment")
}
testenv.MustHaveGoBuild(t)
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", binary)
output, err := cmd.CombinedOutput()
if err != nil {
failed = true
fmt.Fprintf(os.Stderr, "%s\n", output)
t.Fatal(err)
}
built = true
}
func vetCmd(t *testing.T, arg, pkg string) *exec.Cmd {
cmd := exec.Command(testenv.GoToolPath(t), "vet", "-vettool="+binary, arg, path.Join("cmd/vet/testdata", pkg))
cmd.Env = os.Environ()
return cmd
}
func TestVet(t *testing.T) {
t.Parallel()
Build(t)
for _, pkg := range []string{
"asm",
"assign",
"atomic",
"bool",
"buildtag",
"cgo",
"composite",
"copylock",
"deadcode",
"httpresponse",
"lostcancel",
"method",
"nilfunc",
"print",
"rangeloop",
"shift",
"structtag",
"testingpkg",
// "testtag" has its own test
"unmarshal",
"unsafeptr",
"unused",
} {
pkg := pkg
t.Run(pkg, func(t *testing.T) {
t.Parallel()
// Skip cgo test on platforms without cgo.
if pkg == "cgo" && !cgoEnabled(t) {
return
}
cmd := vetCmd(t, "-printfuncs=Warn,Warnf", pkg)
// The asm test assumes amd64.
if pkg == "asm" {
cmd.Env = append(cmd.Env, "GOOS=linux", "GOARCH=amd64")
}
dir := filepath.Join("testdata", pkg)
gos, err := filepath.Glob(filepath.Join(dir, "*.go"))
if err != nil {
t.Fatal(err)
}
asms, err := filepath.Glob(filepath.Join(dir, "*.s"))
if err != nil {
t.Fatal(err)
}
var files []string
files = append(files, gos...)
files = append(files, asms...)
errchk(cmd, files, t)
})
}
}
func cgoEnabled(t *testing.T) bool {
// Don't trust build.Default.CgoEnabled as it is false for
// cross-builds unless CGO_ENABLED is explicitly specified.
// That's fine for the builders, but causes commands like
// 'GOARCH=386 go test .' to fail.
// Instead, we ask the go command.
cmd := exec.Command(testenv.GoToolPath(t), "list", "-f", "{{context.CgoEnabled}}")
out, _ := cmd.CombinedOutput()
return string(out) == "true\n"
}
func errchk(c *exec.Cmd, files []string, t *testing.T) {
output, err := c.CombinedOutput()
if _, ok := err.(*exec.ExitError); !ok {
t.Logf("vet output:\n%s", output)
t.Fatal(err)
}
fullshort := make([]string, 0, len(files)*2)
for _, f := range files {
fullshort = append(fullshort, f, filepath.Base(f))
}
err = errorCheck(string(output), false, fullshort...)
if err != nil {
t.Errorf("error check failed: %s", err)
}
}
// TestTags verifies that the -tags argument controls which files to check.
func TestTags(t *testing.T) {
t.Parallel()
Build(t)
for tag, wantFile := range map[string]int{
"testtag": 1, // file1
"x testtag y": 1,
"othertag": 2,
} {
tag, wantFile := tag, wantFile
t.Run(tag, func(t *testing.T) {
t.Parallel()
t.Logf("-tags=%s", tag)
cmd := vetCmd(t, "-tags="+tag, "tagtest")
output, err := cmd.CombinedOutput()
want := fmt.Sprintf("file%d.go", wantFile)
dontwant := fmt.Sprintf("file%d.go", 3-wantFile)
// file1 has testtag and file2 has !testtag.
if !bytes.Contains(output, []byte(filepath.Join("tagtest", want))) {
t.Errorf("%s: %s was excluded, should be included", tag, want)
}
if bytes.Contains(output, []byte(filepath.Join("tagtest", dontwant))) {
t.Errorf("%s: %s was included, should be excluded", tag, dontwant)
}
if t.Failed() {
t.Logf("err=%s, output=<<%s>>", err, output)
}
})
}
}
// All declarations below were adapted from test/run.go.
// errorCheck matches errors in outStr against comments in source files.
// For each line of the source files which should generate an error,
// there should be a comment of the form // ERROR "regexp".
// If outStr has an error for a line which has no such comment,
// this function will report an error.
// Likewise if outStr does not have an error for a line which has a comment,
// or if the error message does not match the <regexp>.
// The <regexp> syntax is Perl but it's best to stick to egrep.
//
// Sources files are supplied as fullshort slice.
// It consists of pairs: full path to source file and its base name.
func errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) {
var errs []error
out := splitOutput(outStr, wantAuto)
// Cut directory name.
for i := range out {
for j := 0; j < len(fullshort); j += 2 {
full, short := fullshort[j], fullshort[j+1]
out[i] = strings.ReplaceAll(out[i], full, short)
}
}
var want []wantedError
for j := 0; j < len(fullshort); j += 2 {
full, short := fullshort[j], fullshort[j+1]
want = append(want, wantedErrors(full, short)...)
}
for _, we := range want {
var errmsgs []string
if we.auto {
errmsgs, out = partitionStrings("<autogenerated>", out)
} else {
errmsgs, out = partitionStrings(we.prefix, out)
}
if len(errmsgs) == 0 {
errs = append(errs, fmt.Errorf("%s:%d: missing error %q", we.file, we.lineNum, we.reStr))
continue
}
matched := false
n := len(out)
for _, errmsg := range errmsgs {
// Assume errmsg says "file:line: foo".
// Cut leading "file:line: " to avoid accidental matching of file name instead of message.
text := errmsg
if _, suffix, ok := strings.Cut(text, " "); ok {
text = suffix
}
if we.re.MatchString(text) {
matched = true
} else {
out = append(out, errmsg)
}
}
if !matched {
errs = append(errs, fmt.Errorf("%s:%d: no match for %#q in:\n\t%s", we.file, we.lineNum, we.reStr, strings.Join(out[n:], "\n\t")))
continue
}
}
if len(out) > 0 {
errs = append(errs, fmt.Errorf("Unmatched Errors:"))
for _, errLine := range out {
errs = append(errs, fmt.Errorf("%s", errLine))
}
}
if len(errs) == 0 {
return nil
}
if len(errs) == 1 {
return errs[0]
}
var buf bytes.Buffer
fmt.Fprintf(&buf, "\n")
for _, err := range errs {
fmt.Fprintf(&buf, "%s\n", err.Error())
}
return errors.New(buf.String())
}
func splitOutput(out string, wantAuto bool) []string {
// gc error messages continue onto additional lines with leading tabs.
// Split the output at the beginning of each line that doesn't begin with a tab.
// <autogenerated> lines are impossible to match so those are filtered out.
var res []string
for _, line := range strings.Split(out, "\n") {
line = strings.TrimSuffix(line, "\r") // normalize Windows output
if strings.HasPrefix(line, "\t") {
res[len(res)-1] += "\n" + line
} else if strings.HasPrefix(line, "go tool") || strings.HasPrefix(line, "#") || !wantAuto && strings.HasPrefix(line, "<autogenerated>") {
continue
} else if strings.TrimSpace(line) != "" {
res = append(res, line)
}
}
return res
}
// matchPrefix reports whether s starts with file name prefix followed by a :,
// and possibly preceded by a directory name.
func matchPrefix(s, prefix string) bool {
i := strings.Index(s, ":")
if i < 0 {
return false
}
j := strings.LastIndex(s[:i], "/")
s = s[j+1:]
if len(s) <= len(prefix) || s[:len(prefix)] != prefix {
return false
}
if s[len(prefix)] == ':' {
return true
}
return false
}
func partitionStrings(prefix string, strs []string) (matched, unmatched []string) {
for _, s := range strs {
if matchPrefix(s, prefix) {
matched = append(matched, s)
} else {
unmatched = append(unmatched, s)
}
}
return
}
type wantedError struct {
reStr string
re *regexp.Regexp
lineNum int
auto bool // match <autogenerated> line
file string
prefix string
}
var (
errRx = regexp.MustCompile(`// (?:GC_)?ERROR(NEXT)? (.*)`)
errAutoRx = regexp.MustCompile(`// (?:GC_)?ERRORAUTO(NEXT)? (.*)`)
errQuotesRx = regexp.MustCompile(`"([^"]*)"`)
lineRx = regexp.MustCompile(`LINE(([+-])([0-9]+))?`)
)
// wantedErrors parses expected errors from comments in a file.
func wantedErrors(file, short string) (errs []wantedError) {
cache := make(map[string]*regexp.Regexp)
src, err := os.ReadFile(file)
if err != nil {
log.Fatal(err)
}
for i, line := range strings.Split(string(src), "\n") {
lineNum := i + 1
if strings.Contains(line, "////") {
// double comment disables ERROR
continue
}
var auto bool
m := errAutoRx.FindStringSubmatch(line)
if m != nil {
auto = true
} else {
m = errRx.FindStringSubmatch(line)
}
if m == nil {
continue
}
if m[1] == "NEXT" {
lineNum++
}
all := m[2]
mm := errQuotesRx.FindAllStringSubmatch(all, -1)
if mm == nil {
log.Fatalf("%s:%d: invalid errchk line: %s", file, lineNum, line)
}
for _, m := range mm {
replacedOnce := false
rx := lineRx.ReplaceAllStringFunc(m[1], func(m string) string {
if replacedOnce {
return m
}
replacedOnce = true
n := lineNum
if strings.HasPrefix(m, "LINE+") {
delta, _ := strconv.Atoi(m[5:])
n += delta
} else if strings.HasPrefix(m, "LINE-") {
delta, _ := strconv.Atoi(m[5:])
n -= delta
}
return fmt.Sprintf("%s:%d", short, n)
})
re := cache[rx]
if re == nil {
var err error
re, err = regexp.Compile(rx)
if err != nil {
log.Fatalf("%s:%d: invalid regexp \"%#q\" in ERROR line: %v", file, lineNum, rx, err)
}
cache[rx] = re
}
prefix := fmt.Sprintf("%s:%d", short, lineNum)
errs = append(errs, wantedError{
reStr: rx,
re: re,
prefix: prefix,
auto: auto,
lineNum: lineNum,
file: short,
})
}
}
return
}
```
1.4 - Go Modules Reference
1.4.1 - 简介
Introduction 简介
模块是Go管理依赖关系的方式。
本文档是关于 Go 的模块系统的详细参考手册。关于创建 Go 项目的介绍,请参见 How to Write Go Code(如何编写 Go 代码)。有关使用模块、将项目迁移到模块以及其他主题的信息,请参见从 Using Go Modules(使用 Go 模块)开始的博客系列。
1.4.2 - 模块、包和版本
Modules, packages, and versions 模块、包和版本
原文:https://go.dev/ref/mod#modules-overview
模块是发布、版本化和一起分发的包的集合。模块可以直接从版本控制存储库或模块代理服务器上下载。
模块由模块路径来识别,该路径在 go.mod 文件中声明,同时还有关于该模块的依赖项信息。模块根目录是包含go.mod文件的目录。主模块是包含调用go命令的目录的模块。
模块内的每个包是同一目录下的源文件的集合,这些文件被编译在一起。包路径是与包含包(相对于模块根目录)的子目录相连接的模块路径。例如,模块 “golang.org/x/net“在 “html“目录下包含一个包。那个包的路径是 “golang.org/x/net/html"。
Module paths 模块路径
模块路径是模块的规范名称,在模块的 go.mod 文件中用module指令声明。模块的路径是该模块中包路径的前缀。
模块路径应该同时描述模块的作用和查找模块的位置。通常,模块路径由存储库根路径、存储库中的目录(通常为空)和主版本后缀(仅适用于主版本2或更高版本)组成。
- 存储库根路径是模块路径中与开发模块的版本控制存储库的根目录相对应的部分。大多数模块都定义在其存储库的根目录下,所以这通常是整个路径。例如,
golang.org/x/net是同名模块的存储库根目录。关于go命令如何使用从模块路径派生的 HTTP 请求来定位存储库的信息,请参见Finding a repository for a module path(寻找模块路径的存储库)。 - 如果模块没有定义在存储库的根目录中,模块子目录是模块路径中命名目录的一部分,不包括主版本后缀。这也可以作为语义版本标签的前缀。例如,模块
golang.org/x/tools/gopls位于根目录golang.org/x/tools的gopls子目录中,所以它的模块子目录是gopls。参见Mapping versions to commits和Module directories within a repository。 - 如果模块是在主版本2或更高版本发布的,模块路径必须以主版本后缀结尾,如
/v2。这可能是也可能不是子目录名称的一部分。例如,路径为golang.org/x/repo/sub/v2的模块可能在golang.org/x/repo仓库的/sub或/sub/v2子目录下。
如果模块可能被其他模块所依赖,就必须遵循这些规则,以便go命令能够找到并下载该模块。对于模块路径中允许的字符也有一些lexical restrictions(词法限制)。
Versions 版本
一个版本标识了模块的不可改变的快照,它可以是一个发布版或预发布版。每个版本以字母v开头,后面是语义版本。关于如何对版本进行格式化、解释和比较的细节,请参见Semantic Versioning 2.0.0(语义化版本2.0.0)。
简而言之,语义版本由三个非负整数(从左到右分别为:主版本号,次版本号,修订版本号)组成,中间用点分开。修订版本号后面可以有一个以连字符(-或+)开头的可选预发布字符串。预发布字符串或补丁版本后面可以有一个以加号开头的构建元数据字符串。例如,v0.0.0、v1.12.134、v8.0.5-pre和v2.0.9+meta是有效的版本。
版本的每一部分都指示该版本是否稳定,以及是否与以前的版本兼容。
-
在对模块的公共接口或文档功能进行了向后不兼容的更改(例如,在删除了一个包)之后,major version(主版本号)必须被递增,次版本号和修订版本号必须被设置为零。
-
在进行向后兼容的更改(例如,增加了一个新的功能)之后,minor version(次版本号)必须被递增,修订版本号必须被设置为零。
-
patch version(修订版本号)必须在不影响模块的公共接口的更改(例如错误修复或优化)之后被递增。
-
pre-release (预发布)后缀表示版本是预发布版本。预发布版本在相应的发布版本之前排序。例如,
v1.2.3-pre排在v1.2.3之前。 -
在比较版本时,build metadata的后缀被忽略。带有build metadata的标签在版本控制存储库中被忽略,但build metadata在 go.mod 文件中指定的版本中被保留下来。后缀
+incompatible表示在迁移到模块版本主版本2或更高版本之前发布的版本(参见与非模块存储库的兼容性)。
如果一个版本的主版本号是0,或者它有一个预发布的后缀,则被认为是不稳定的。不稳定的版本不受兼容性要求的限制。例如,v0.2.0 可能与 v0.1.0 不兼容,v1.5.0-beta 可能与 v1.5.0 不兼容。
Go可以使用不遵循这些约定的标签、分支或修订版来访问在版本控制系统的模块。然而,在主模块中,go命令会自动将不遵循此标准的修订版名称转换为规范的版本号。在这个过程中,go命令也会删除build metadata的后缀(除了+incompatible)。这可能会产生一个pseudo-version(伪版本号),一个编码修订版标识符(如Git提交的哈希值)的预先发布的版本号和一个版本控制系统的时间戳。例如,命令go get golang.org/x/net@daa7c041将把提交的哈希值daa7c041转换为伪版本v0.0.0-20191109021931-daa7c04131f5。 在主模块之外需要规范的版本,如果在 go.mod 文件中出现类似master的非规范版本,go命令将报告错误。
Pseudo-versions 伪版本号
伪版本号是一个特殊格式的pre-release version(预发布版本号),它对版本控制存储库中的特定版本信息进行编码。例如,v0.0.0-20191109021931-daa7c04131f5就是一个伪版本号。
伪版本号可以指那些没有语义版本标签可用的修订版。例如,在开发分支上创建版本标签之前,可以使用它们来测试提交的内容。
每个伪版本都有三个部分:
- 基础版本前缀(
base version prefix)(vX.0.0或vX.Y.Z-0),该前缀来自于该修订版之前的语义版本标签,如果没有这样的标签,则是vX.0.0。 - 时间戳(
timestamp)(yyyymmddhhmmss),这是修订版创建的UTC时间。在Git中,这是提交的时间,而不是作者时间。 - 修订版标识符(
revision identifier)(abcdefabcdef),它是提交哈希值的一个12个字符的前缀,或者在Subversion中,是一个零填充的修订号。
每个伪版本可以是三种形式之一,取决于基础版本(base version)。这些形式保证了伪版本比其基础版本高,但比下一个标记的版本低。
vX.0.0-yyyymmddhhmmss-abcdefabcdef在没有已知基础版本时使用。与所有版本一样,主版本X必须与模块的major version suffix(主版本后缀)相匹配。vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef在基础版本是预发布版本(如vX.Y.Z-pre)时使用。vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef在基础版本是发布版本(如vX.Y.Z)时使用。例如,如果基础版本是v1.2.3,那么伪版本可能是v1.2.4-0.20191109021931-daa7c04131f5。
通过使用不同的基础版本,多个伪版本可以引用相同的提交。这发生在写完伪版本后,低版本被标记的时候。
这些形式给了伪版本两个有用的属性:
- 具有已知基础版本的伪版本排序高于这些版本,但低于其他预发布的后续版本。
- 具有相同基础版本前缀的伪版本按时间顺序排序。
go命令进行了一些检查,以确保模块作者能够控制伪版本与其他版本的比较,并确保伪版本引用的修订版是实际属于模块提交历史的一部分。
- 如果指定了基础版本(base version),就必须有相应的语义版本标签,该标签是伪版本所描述的修订版的祖先。这可以防止开发者使用伪版本来绕过minimal version selection(最小版本)的选择,该伪版本比所有标签的版本(比如
v1.999.999-9999999999-daa7c04131f5)都要高。 - 时间戳(timestamp)必须与修订版的时间戳匹配。这可以防止攻击者用无限数量的其他相同伪版本来 flooding module proxies (模块代理)。这也可以防止模块使用者更改版本的相对顺序。
- 修订版必须是模块存储库的一个分支或标签的祖先。这可以防止攻击者引用未经批准的更改或拉取请求。
伪版本从不需要手工输入。许多命令接受提交哈希值或分支名称,并将其自动翻译成伪版本(或标签版本(如果可用))。比如说:
go get example.com/mod@master
go list -m -json example.com/mod@abcd1234
Major version suffixes 主版本的后缀
从主版本2开始,模块路径必须有一个主版本后缀,如/v2,与主版本相匹配。例如,如果模块的路径example.com/mod是v1.0.0版本,那么它的路径example.com/mod/v2必须是v2.0.0版本。
主版本后缀实现了import compatibility rule(导入兼容性规则):
如果旧包和新包有相同的导入路径,则新包必须向后兼容旧包。
根据定义,模块的新的主版本中的包不向后兼容之前的主版本中的相应包。因此,从v2开始,包需要新的导入路径。这是通过在模块路径上添加一个主版本的后缀来实现的。由于模块路径是模块内每个包的导入路径的前缀,在模块路径上添加主版本后缀为每个不兼容的版本提供了一个不同的导入路径。
主版本后缀在主版本v0或v1时是不允许的。没有必要在v0和v1之间改变模块路径,因为v0版本是不稳定的,没有兼容性保证。此外,对于大多数模块来说,v1是向后兼容最后一个v0版本的;v1版本是对兼容性的一种承诺,而不是表明与v0相比有不兼容的变化。
作为一种特殊情况,以gopkg.in/开始的模块路径必须始终有一个主版本后缀,即使是v0和v1。 后缀必须以点开始,而不是斜线(例如,gopkg.in/yaml.v2)。
主版本后缀允许模块的多个主版本共存于同一个构建中。这可能是由于diamond dependency problem(钻石依赖性问题)而需要的。通常,如果一个模块在两个不同的版本中被传递依赖关系所需要,则将使用更高的版本。然而,如果这两个版本不兼容,那么这两个版本都不能满足所有的客户。由于不兼容的版本必须有不同的主版本号,因此由于主版本后缀,它们也必须具有不同的模块路径。这就解决了冲突:具有不同后缀的模块被视为独立的模块,它们的包 —— 即使是相对于它们的模块根的同一子目录下的包 —— 也是不同的。
许多Go项目在迁移到模块之前(也许在模块被引入之前)发布了v2或更高的版本,但没有使用主版本后缀。这些版本使用+incompatible的构建标签进行注释(例如,v2.0.0+incompatible)。更多信息请参见Compatibility with non-module repositories(与非模块存储库的兼容性)。
Resolving a package to a module 将一个包解析为模块
当 go 命令使用package path(包路径)加载包时,它需要确定哪个模块提供该包。
go命令首先在build list(构建列表)中搜索路径为包路径前缀的模块。例如,如果包 example.com/a/b 被导入,并且模块 example.com/a 在构建列表中,go 命令将在目录 b 中检查 example.com/a 是否包含该包。在一个目录中至少要有一个扩展名为 .go 的文件,才能被视为一个包。Build constraints(构建限制)并不适用这个目的。如果在构建列表中正好有模块提供了该包,那么就使用该模块。如果没有模块提供该包,或者有两个或更多的模块提供该包,go命令会报告一个错误。-mod=mod标志指示go命令尝试寻找提供缺失包的新模块,并更新go.mod和go.sum。go get和go mod tidy命令会自动完成这项工作。
当go命令查找一个包路径的新模块时,它会检查GOPROXY环境变量,它是一个用逗号分隔的代理URL列表或关键词direct或off。代理URL表示go命令应该使用GOPROXY 协议与模块代理联系。direct表示go命令应该与一个版本控制系统通信。GOPRIVATE和GONOPROXYenvironment variables(环境变量)也可以用来控制这种行为。
对于GOPROXY列表中的每个条目,go命令请求可能提供包(即包路径的每个前缀)的每个模块路径的最新版本。对于每个成功请求的模块路径,go命令将下载最新版本的模块,并检查该模块是否包含请求的包。如果一个或多个模块包含所请求的包,则使用路径最长的模块。如果找到一个或多个模块,但没有一个包含所请求的包,则报告错误。如果没有找到模块,go命令将尝试GOPROXY列表中的下一个条目。如果没有剩余的条目,则报告错误。
例如,假设go命令正在寻找一个提供包golang.org/x/net/html的模块,并且GOPROXY被设置为https://corp.example.com,https://proxy.golang.org。go命令可能会发出以下请求:
-
向
https://corp.example.com/(并行):- 请求
golang.org/x/net/html的最新版本 - 请求
golang.org/x/net的最新版本 - 请求
golang.org/x的最新版本 - 请求
golang.org的最新版本
- 请求
-
如果向
https://corp.example.com/的所有请求都以404或410失败告终,则向https://proxy.golang.org/:- 请求
golang.org/x/net/html的最新版本 - 请求
golang.org/x/net的最新版本 - 请求
golang.org/x的最新版本 - 请求
golang.org的最新版本
- 请求
在找到合适的模块后,go 命令将使用新模块的路径和版本向主模块的 go.mod 文件添加一个新的requirement(需求)。这样可以确保将来加载相同的包时,会使用相同版本的模块。如果解析后的包没有被主模块中的包导入,那么新的需求将会有一个// indirect的注释。
1.4.3 - go.mod 文件
go.mod files - go.mod 文件
模块由其根目录下的名为go.mod的UTF-8编码的文本文件来定义。go.mod文件是以行为单位的。每一行都有一个单独指令,由关键字后跟参数组成。例如:
module example.com/my/thing
go 1.12
require example.com/other/thing v1.0.2
require example.com/new/thing/v2 v2.3.4
exclude example.com/old/thing v1.2.3
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
retract [v1.9.0, v1.9.5]
可以将前导关键字从相邻的行中分解出来,以创建一个块,就像Go导入中一样。
require (
example.com/new/thing/v2 v2.3.4
example.com/old/thing v1.2.3
)
go.mod文件被设计成人类可读,机器可写。go命令提供了几个改变go.mod文件的子命令。例如,go get可以升级或降级特定的依赖项。加载模块图的命令会在需要时automatically update(自动更新)go.mod。go mod edit可以执行低级别的编辑。Go程序可以使用golang.org/x/mod/modfile包,以编程方式进行同样的修改。
main module(主模块)和任何用本地文件路径指定的replacement module(替换模块)都需要go.mod文件。然而,缺少显式的go.mod文件的模块仍然可以作为依赖项被要求,或者作为用模块路径和版本指定的替换模块使用;参见Compatibility with non-module repositories(与非模块存储库的兼容性)。
Lexical elements 词法元素
当go.mod文件被解析时,其内容被分解为一连串的标记。有几种标记:空白(whitespace)、注释(comments)、标点符号(punctuation)、关键字(keywords)、标识符(identifiers)和字符串(strings)。
空白(White space)包括空格(U+0020)、制表符(U+0009)、回车符(U+000D)和换行符(U+000A)。除换行符外,其他空白字符没有任何作用,只是将原本合并的标记分开。换行符是重要的标记。
注释(Comments)以//开始并运行到行尾。/* */ 的注释是不允许的。
标点符号(Punctuation)包括(、)和=>。
关键字(Keywords)用于区分go.mod文件中不同类型的指令。允许的关键字有module、go、require、replace、exclude和retract。
标识符(Identifiers)是由非空白字符组成的序列,例如模块路径或语义版本。
字符串(Strings)是有引号的字符序列。有两种字符串:以引号(",U+0022)开头和结尾的解释字符串(interpreted strings)和以重音符号(`,U+0060)开头和结尾的原始字符串(raw strings)。被解释的字符串可以包含由反斜线(, U+005C)和其他字符组成的转义序列。转义的引号(\")不会终止解释字符串。解释字符串(interpreted strings)的无引号值是引号之间的字符序列,每个转义序列被反斜线后面的字符取代(例如,\“被 “取代,\n被n取代)。相比之下,原始字符串的无引号值只是重音符号之间的字符序列;反斜杠在原始字符串中没有特殊意义。
在go.mod语法中,标识符和字符串是可以互换的。
Module paths and versions 模块路径和版本
go.mod文件中的大多数标识符和字符串都是模块路径或版本。
模块路径必须满足以下要求:
- 路径必须由一个或多个路径元素组成,以斜线(
/,U+002F)分隔。路径不能以斜线开始或结束。 - 每个路径元素是一个非空字符串,由ASCII字母、ASCII数字和有限的ASCII标点符号(
-、.、_和~)组成。 - 路径元素不能以点(
.,U+002E)开始或结束。 - 路径元素前缀到第一个点不能是Windows上的保留文件名,无论大小写(
CON、com1、NuL等)。 - 路径元素前缀到第一个点不能以一个波浪符号后跟一个或多个数字结尾(如
EXAMPL~1.COM)。
如果模块路径出现在require指令中并且没有被替换,或者模块路径出现在replace指令的右侧,go命令可能需要下载该路径的模块,并且必须满足一些额外的要求。
(a)按照惯例,域名的前导路径元素(直到第一个斜线)必须只包含小写的 ASCII 字母、 ASCII 数字、点(.,U+002E)和破折号(- ,U+002D) ;它必须包含至少一个点,并且不能以破折号开始。
(b)对于形式为/vN的最后路径元素,其中N看起来是数字(ASCII数字和点),N不能以前导零开始,不能是/v1,也不能包含任何点。
- 对于以
gopkg.in/开头的路径,这个要求被一个路径必须遵循 gopkg.in服务约定的要求所取代。
go.mod文件中的版本可以是[经典(canonical)](../Glossary#canonical version)的或非经典的。
经典版本以字母v开头,后面是符合Semantic Versioning 2.0.0(语义化版本2.0.0)规范的语义版本。更多信息请参见 Versions(版本)。
大多数其他标识符和字符串都可以作为非经典版本使用,但是也有一些限制,以避免文件系统、存储库和module proxies(模块代理)出现问题。非经典版本只允许在主模块的go.mod文件中使用。go命令在自动更新go.mod文件时,会尝试用一个等效的经典版本来替换每个非经典版本。
在模块路径与版本相关的地方(如require、replace和exclude指令),最后的路径元素必须与版本一致。参见Major version suffixes(主版本后缀)。
Grammar 语法
go.mod的语法是使用Extended Backus-Naur Form (EBNF)指定的。关于EBNF语法的详细信息,请参见Notation section in the Go Language Specification(Go语言规范中的标记法部分)。
GoMod = { Directive } .
Directive = ModuleDirective |
GoDirective |
RequireDirective |
ExcludeDirective |
ReplaceDirective |
RetractDirective .
换行符、标识符和字符串分别用newline、ident和string表示。
模块路径和版本用ModulePath和Version来表示。
ModulePath = ident | string . /* see restrictions above */
Version = ident | string . /* see restrictions above */
module directive
module指令定义了主模块的path(路径)。go.mod文件必须恰好包含一个module指令。
ModuleDirective = "module" ( ModulePath | "(" newline ModulePath newline ")" ) newline .
示例:
module golang.org/x/net
Deprecation 废弃
模块可以在段落开头包含字符串 Deprecated:(区分大小写)的注释块中标记为已弃用。 废弃信息从冒号之后开始,一直到段落的末尾。注释可以出现在module指令的前面,也可以出现在同一行的后面。
示例:
// Deprecated: use example.com/mod/v2 instead.
module example.com/mod
从Go 1.17开始,go list -m -u检查build list(构建列表)中所有已废弃模块的信息。go get检查构建命令行上命名的包所需的已废弃模块。
当go命令检索一个模块的废弃信息时,它从匹配@latestversion query(版本查询)的版本中加载go.mod文件,而不考虑retractions(撤回)或exclusions(排除)。go命令从同一个go.mod文件中加载retracted versions(撤回版本)的列表。
为了废弃一个模块,作者可以添加一个// Deprecated:注释并标记一个新版本。作者可以在更高的版本中更改或删除废弃信息。
废弃适用于一个模块的所有次版本。高于v2的主版本被认为是独立的模块,因为它们的major version suffixes(主版本后缀)赋予它们不同的模块路径。
Deprecation messages are intended to inform users that the module is no longer supported and to provide migration instructions, for example, to the latest major version. Individual minor and patch versions cannot be deprecated; retract may be more appropriate for that.
废弃信息的目的是通知用户,该模块不再被支持,并提供迁移说明,例如,迁移到最新的主版本。单个次版本和修订版本不能被废弃(=>仍有疑问??);retract可能更适合于这种情况。
go directive
go指令表明一个模块是以给定的Go版本的语义为基础编写的。版本必须是有效的Go发布版本:一个正整数,后面跟一个点和一个非负整数(例如,1.9,1.14)。
go指令最初是为了支持Go语言的向后不兼容的变化(见Go 2 过渡)。自从引入模块以来,没有任何不兼容的语言变化,但go指令仍然影响到新语言特性的使用:
- 对于模块中的包,编译器会拒绝使用
go指令指定的版本之后引入的语言特性。例如,如果模块的指令是go 1.12,它的包就不能使用1_000_000这样的数字字面量,这是在Go 1.13引入的。 - 如果较旧的Go版本构建了该模块的一个包并遇到了编译错误,那么错误就会指出该模块是为一个较新的Go版本编写的。例如,假设模块有
go 1.13,一个包使用数字字面1_000_000。如果该包是用Go 1.12构建的,编译器就会注意到该代码是为Go 1.13编写的。
此外,go命令会根据go指令所指定的版本改变其行为。这有以下影响:
(a)在go 1.14或更高版本中,可以启用自动vendoring。如果文件vendor/modules.txt存在并与go.mod一致,就不需要显式使用-mod=vendor标志。
(b)在 go 1.16 或更高版本中,all包模式只匹配由main module(主模块)中由包和测试过渡导入的包。这也是go mod vendor自引入模块以来所保留的包的集合。在较低的版本中,all也包括由主模块中的包导入的包的测试、对这些包的测试等等。
(c)在go 1.17或更高版本:
-
go.mod文件包括一个明确的require指令,该指令提供由主模块中的包或测试过渡地导入的任何包。(在go 1.16或更低版本,只有在minimal version selection(最小版本选择)会选择不同版本的情况下,才会包含indirect dependency(间接依赖)。) 这个额外的信息使得module graph pruning(模块图的修剪)和lazy module loading(延迟模块加载)成为可能。 -
由于
// indirect依赖可能比以前的go版本多得多,间接依赖被记录在go.mod文件中的一个独立块中。 -
go mod vendor省略了go.mod和go.sum文件中的供应商依赖项。(这允许在vendor的子目录中调用go命令来识别正确的主模块)。 -
go mod vendor将 go 版本从每个依赖项的 go.mod 文件中记录下来,并放在vendor/modules.txt中。
go.mod文件最多可以包含一个go指令。如果没有go指令,大多数命令会添加一个当前Go版本的go指令。
在Go 1.17发行版中,如果go指令缺失,则假定go 1.16。
GoDirective = "go" GoVersion newline .
GoVersion = string | ident . /* valid release version; see above */
示例:
go 1.14
require directive
require指令声明了给定模块依赖的最低要求版本。对于每个所需的模块版本,go命令加载该版本的go.mod文件,并将该文件中的requirements 纳入其中。一旦所有requirements 被加载完,go命令就会使用minimal version selection(最小版本选择 MVS) 来解析它们,从而产生build list(构建列表)。
go命令自动为一些requirements 添加// indirect注释。// indirect注释表示所需模块的任何包都没有被main module(主模块)中的任何包直接导入。
如果go directive指定了go 1.16或更低的版本,当所选模块的版本高于主模块的其他依赖项已经暗示(过渡地)的版本时,go命令会添加一个间接需求。这可能是由于显式的升级(go get -u ./...),移除之前施加需求的其他依赖项(go mod tidy),或者依赖项导入的包在其自身的go.mod文件中没有相应的 requirement (比如一个完全没有go.mod文件的依赖项)。
在go 1.17及以上版本中,go命令为每个模块增加了一个间接需求,提供任何被主模块中的包或测试导入(即使是间接的)或作为参数传递给go get的包。这些更全面的 requirements 可以支持module graph pruning(模块图的修剪)和lazy module loading(延迟模块加载)。
RequireDirective = "require" ( RequireSpec | "(" newline { RequireSpec } ")" newline ) .
RequireSpec = ModulePath Version newline .
示例:
require golang.org/x/net v1.2.3
require (
golang.org/x/crypto v1.4.5 // indirect
golang.org/x/text v1.6.7
)
exclude directive
exclude指令可以防止模块版本被go命令加载。
从Go 1.16开始,如果任何go.mod文件中的require指令所引用的版本被主模块的go.mod文件中的exclude指令所排除,该requirement 将被忽略。这可能会导致像go get和go mod tidy这样的命令在go.mod中添加更高版本的新requirements ,如果合适的话,会加上一个// indirect注释。
在Go 1.16之前,如果一个排除的版本被require指令引用,go命令会列出该模块的可用版本(如go list -m -versions所示)并加载下一个较高的非排除版本。这可能会导致不确定的版本选择,因为下一个更高版本可能会随着时间的推移而改变。为了这个目的,发布版和预布行版都被考虑了,但伪版本没有被考虑。如果没有更高的版本,go命令会报告一个错误。
exclude指令只适用于主模块的go.mod文件,在其他模块中被忽略。详见Minimal version selection(最小版本选择 MVS)。
ExcludeDirective = "exclude" ( ExcludeSpec | "(" newline { ExcludeSpec } ")" newline ) .
ExcludeSpec = ModulePath Version newline .
示例:
exclude golang.org/x/net v1.2.3
exclude (
golang.org/x/crypto v1.4.5
golang.org/x/text v1.6.7
)
replace directive
replace指令用其他地方找到的内容替换某个模块的特定版本或某个模块的所有版本。替换可以指定另一个模块路径和版本,或者一个特定平台的文件路径。
如果一个版本出现在箭头(=>)的左侧,那么只有该模块的特定版本被替换,其他版本将被正常访问。如果左侧的版本被省略,则模块的所有版本都被替换。
如果箭头右侧的路径是一个绝对或相对路径(以./或./开头),它被解释为替换模块根目录的本地文件路径,其中必须包含一个go.mod文件。在这种情况下,替换版本必须被省略。
如果右边的路径不是本地路径,它必须是一个有效的模块路径。在这种情况下,需要一个版本号。同一模块的版本不能同时出现在构建列表中。
不管替换是用本地路径还是模块路径指定的,如果替换的模块有一个go.mod文件,它的module指令必须与它所替换的模块路径一致。
replace指令只适用于主模块的go.mod文件,在其他模块中被忽略。详见Minimal version selection(最小版本选择 MVS)。
如果有多个主模块,所有主模块的go.mod文件都适用。不允许主模块间的replace指令发生冲突,必须在go.work 文件的替换中删除或重写这些指令。
请注意,仅仅是replace指令并不能将一个模块添加到模块图中。在主模块的 go.mod 文件或依赖模块的 go.mod 文件中,还需要一个指向被替换模块版本的 require 指令。如果不需要左侧的模块版本,replace指令就没有作用。
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
示例:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
retract directive
retract指令表示由go.mod定义的模块的某个版本或一系列版本不应该被依赖。当版本过早发布或在发布后发现严重问题时,retract指令就很有用。撤回的版本应该在版本控制存储库和module proxy(模块代理)上保持可用,以确保依赖它们的构建不会被破坏。retract这个词是从学术文献中借来的:被撤回的研究论文仍然可以使用,但它有问题,不应该成为未来工作的基础。
当一个模块的版本被撤回时,用户将不会使用go get、go mod tidy或其他命令自动升级到该版本。依赖于撤消版本的构建应该继续工作,但是当用户用go list -m -u检查更新或用go get更新相关模块时,将会收到撤回的通知。
要撤回一个版本,模块作者应该在go.mod中添加一个retract指令,然后发布一个包含该指令的新版本。新版本必须高于其他发布或预发布的版本;也就是说,在考虑撤回之前,@latestversion query(版本查询)应该解析到新版本。go命令从go list -m -retracted $modpath@latest(其中$modpath是模块路径)显示的版本中加载和应用撤回。
除非使用 -retracted 标志,否则撤回的版本会从 go list -m -versions 打印的版本列表中隐藏。在解析版本查询(如@>=v1.2.3或@latest)时,撤回的版本将被排除。
包含撤回的版本可以自行撤回。如果一个模块的最高发布版本或预发布版本自行撤回了,@latest查询会在排除撤回的版本后解析到一个较低的版本。
As an example, consider a case where the author of module example.com/m publishes version v1.0.0 accidentally. To prevent users from upgrading to v1.0.0, the author can add two retract directives to go.mod, then tag v1.0.1 with the retractions.
举个例子,考虑这样一种情况:模块 example.com/m 的作者意外地发布了 v1.0.0 版本。为了防止用户升级到v1.0.0,作者可以在go.mod中添加两个retract指令,然后用撤回标记v1.0.1。
retract (
v1.0.0 // Published accidentally.
v1.0.1 // Contains retractions only.
)
当用户运行go get example.com/m@latest时,go命令会读取v1.0.1版本的撤回,这就是现在的最高版本。v1.0.0和v1.0.1都被撤回了,所以go命令会升级(或降级!)到下一个最高版本,也许是v0.9.5。
retract指令既可以写成单一版本(如v1.0.0),也可以写成有上下限的封闭的版本区间,用[ 和 ] 界定(如[v1.1.0, v1.2.0])。单一版本等同于一个上界和下界相同的区间。和其他指令一样,多个retract指令可以组合在一起,以(为界,放在一行的末尾,以)为界,放在单独的一行。
每条retract指令都应该有一个注释,解释撤回的理由,尽管这并不是强制性的。go命令可以在关于撤回版本的警告和go list输出中显示理由注释。理由注释可以紧接着写在retract指令的上方(中间没有空行),也可以写在同一行的后面。如果一条注释出现在一个块的上方,它适用于该块内所有没有自己注释的retract指令。一个理由注释可以跨越多行。
RetractDirective = "retract" ( RetractSpec | "(" newline { RetractSpec } ")" newline ) .
RetractSpec = ( Version | "[" Version "," Version "]" ) newline .
示例:
- 撤回
v1.0.0到v1.9.9之间的所有版本:
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)
- 在提前发布了
v1.0.0版本之后,返回到 unversioned:
retract [v0.0.0, v1.0.1] // assuming v1.0.1 contains this retraction.
- 抹去包含所有伪版本和标签版本的模块:
retract [v0.0.0-0, v0.15.2] // assuming v0.15.2 contains this retraction.
retract指令是在Go 1.16中添加的。如果主模块的go.mod文件中写有retract指令,Go 1.15及以下版本将报告错误,并忽略依赖模块的go.mod文件中的retract指令。
Automatic updates 自动更新
如果go.mod缺少信息或不能准确反映现实,大多数命令都会报告错误。go get和go mod tidy命令可以用来修复大多数这些问题。此外,-mod=mod标志可用于大多数模块感知命令(go build、go test等),指示go命令自动修复go.mod和go.sum中的问题。
例如,考虑这个go.mod文件:
module example.com/M
go 1.16
require (
example.com/A v1
example.com/B v1.0.0
example.com/C v1.0.0
example.com/D v1.2.3
example.com/E dev
)
exclude example.com/D v1.2.3
用 -mod=mod 触发的更新将非经典版本标识符重写为canonical(经典)的 semver 形式,因此 example.com/A 的 v1 变成了 v1.0.0,而 example.com/E 的 dev 变成了 dev 分支上最新提交的伪版本,可能是 v0.0.0-20180523231146-b3f5c0f6e5f1。
该更新修改了requirements 以尊重排除项,因此对排除项 example.com/D v1.2.3 的 requirements 被更新为使用 example.com/D 的下一个可用版本,可能是 v1.2.4 或 v1.3.0。
该更新移除了多余的或误导性的 requirements。例如,如果 example.com/A v1.0.0 本身需要 example.com/B v1.2.0 和 example.com/C v1.0.0,那么 go.mod 对 example.com/B v1.0.0 的 requirement 是误导性的(被 example.com/A 对 v1.2.0 的 requirement 所取代),而它对 example.com/C v1.0.0 的 requirement 是多余的(被 example.com/A 对相同版本的需求暗示),因此两者都将被移除。如果主模块包含直接从example.com/B或example.com/C导入的包,那么requirement 将被保留,但会更新为实际使用的版本。
最后,该更新会将go.mod改成经典格式,这样未来的机械更改将导致最小的差异。如果只需要更改格式,go命令将不更新go.mod。
因为模块图定义了 import 语句的含义,任何加载包的命令也会使用go.mod,因此可以对其进行更新的(命令),包括go build、go get、go install、go list、go test、go mod tidy。
在Go 1.15及以下版本中,-mod=mod标志是默认启用的,所以更新会自动进行。从Go 1.16开始,go命令的行为就像设置了-mod=readonly一样:如果需要对go.mod进行任何更改,go命令会报告一个错误并建议进行修复。
1.4.4 - 最小版本选择 (MVS)
Minimal version selection (MVS) 最小版本选择 (MVS)
Go 使用一种叫做最小版本选择(MVS)的算法来选择一组模块的版本,以便在构建包时使用。在Russ Cox的Minimal Version Selection(最小版本选择)中详细描述了MVS。
从概念上讲,MVS在模块的有向图上操作,用go.mod文件指定。图中的每个顶点代表一个模块版本。每条边代表一个依赖的最小需求版本,用require指令指定。该图可以通过主模块的go.mod文件中的exclude和replace指令以及go.work文件中的replace指令来修改。
MVS 生成build list(构建列表)作为输出,即用于构建的模块版本列表。
MVS 从主模块(图中没有版本的特殊顶点)开始,遍历图,跟踪每个模块所需的最高版本。在遍历结束后,所需的最高版本组成了构建列表:它们是满足所有requirements的最小版本。
可以用 go list -m all 命令来检查构建列表。与其他依赖项管理系统不同,构建列表不保存在一个 “lock"文件中。MVS是确定性的,当新版本的依赖项发布时,构建列表不会改变,因此在每个模块感知命令的开头使用MVS进行计算。
考虑下图中的示例。主模块要求模块 A 的版本为 1.2 或更高,模块 B 的版本为 1.2 或更高。A 1.2和B 1.2分别需要C 1.3和C 1.4。C 1.3和C 1.4都需要D 1.2。
Module version graph with visited versions highlighted
模块版本图,访问过的版本突出显示
MVS访问并加载用蓝色突出显示的每个模块版本的go.mod文件。在该图遍历结束时,MVS返回一个包含加粗版本的构建列表:A 1.2, B 1.2, C 1.4, 和 D 1.2。注意,B和D的更高版本是可用的,但MVS并没有选择它们,因为没有任何东西需要它们。
Replacement 替换
模块的内容(包括它的go.mod文件)可以用主模块的go.mod文件或工作区的go.work文件中的replace指令来替换。replace指令可以应用于模块的特定版本或模块的所有版本。
替换会改变模块图,因为替换的模块可能与被替换的版本有不同的依赖项。
考虑下面的例子,其中 C 1.4被 R 替换。R依赖于D 1.3而不是D 1.2,所以MVS返回一个包含A 1.2、B 1.2、C 1.4(用R替换)和D 1.3的构建列表。
Module version graph with a replacement
带替换的模块版本图
Exclusion 排除
模块也可以用主模块go.mod文件中的exclude 指令在特定的版本中被排除。
排除也会改变模块图。当一个版本被排除时,它被从模块图中移除,对它的 requirements 被重定向到下一个更高版本。
考虑下面的例子。C 1.3 已经被排除。MVS 将表现得好像 A 1.2 需要 C 1.4(下一个更高版本)而不是 C 1.3 。
Module version graph with an exclusion
带排除的模块版本图
Upgrades 升级
go get 命令可以用来升级一组模块。为了执行升级,go 命令在运行 MVS 之前更改了模块图,增加了从访问的版本到升级的版本的 edges (边)。
Consider the example below. Module B may be upgraded from 1.2 to 1.3, C may be upgraded from 1.3 to 1.4, and D may be upgraded from 1.2 to 1.3.
考虑下面的例子。模块 B 可以从 1.2 升级到 1.3,C 可以从 1.3 升级到 1.4,D 可以从 1.2 升级到 1.3。
Module version graph with upgrades
带有升级的模块版本图
升级(和降级)可能会增加或移除间接依赖项。在这种情况下,E 1.1和F 1.1在升级后出现在构建列表中,因为E 1.1是B 1.3所需要的。
为了保护升级,go命令更新了go.mod中的 requirements 。它将更改B的 requirement 为1.3版本。它还将添加对C 1.4和D 1.3的 requirements ,并加上// indirect注释,因为这些版本在其他情况下不会被选中。
Downgrade 降级
go get 命令也可以用来降级一组模块。为了执行降级,go命令通过移除降级后的版本来更改模块图。它也会移除依赖于被移除版本的其他模块的版本,因为它们可能与降级后的依赖版本不兼容。如果主模块需要一个被降级移除的模块版本,该 requirement 将被更改为未被移除的先前版本。如果没有先前的版本,该 requirement 将被放弃。
考虑下面的例子。假设发现 C 1.4 有问题,所以我们降级到 C 1.3。C 1.4被从模块图中移除。B 1.2 也被移除,因为它需要 C 1.4 或更高版本。主模块对B的 requirement 被改为1.1。
Module version graph with downgrade
带有降级的模块版本图
go get也可以完全移除依赖项,在参数后使用@none后缀。这与降级的工作原理类似。所有被命名的模块的版本都会从模块图中移除。
1.4.5 - 模块图的修剪
Module graph pruning 模块图的修剪
如果主模块是go 1.17或更高版本,用于minimal version selection(最小化版本选择)的模块图仅包括每个模块依赖项的 immediate(直接)requirements ,这些依赖项在其自己的 go.mod 文件中指定到go 1.17或更高版本,除非该版本的模块也被go 1.16或更低版本的其他依赖(过渡性)所需要。(go 1.17版本的过渡性依赖项会从模块图中删去)。
由于 go 1.17 的 go.mod 文件包括构建任何包或测试所需的每个依赖项的 require 指令,因此修剪后的模块图包括go build或go testmain module(主模块)明确要求的任何依赖项中的包所需的所有依赖项。不需要构建任何包或测试的模块不能影响其包的运行时行为,因此从模块图中修剪出来的依赖项只会导致其他不相关的模块之间的干扰。
那些 requirements 被修剪掉的模块仍然出现在模块图中,并且仍然被go list -m all报告:它们selected versions(所选择的版本)是已知的并且定义良好,并且包可以从这些模块中加载(例如,作为从其他模块加载的测试的过渡性依赖项)。然而,由于go命令不能轻易识别这些模块的哪些依赖项得到了满足,所以go build和go test的参数不能包括那些 requirements 已被修剪掉的模块的包。 go get将包含每个命名包的模块提升为显式的依赖项,允许在该包上调用go build或go test。
因为Go 1.16和更早的版本不支持模块图的修剪,所以对于每个指定Go 1.16或更低版本的模块来说,完整的依赖项的过渡性闭包 —— 包括过渡性的go 1.17依赖项 —— 仍然被包括在内。(在 go 1.16 及以下版本中,go.mod 文件只包括direct dependencies(直接依赖项),因此必须加载更大的图以确保包括所有间接依赖项)。
默认情况下,go mod tidy为模块记录的 go.sum 文件 包括Go 版本在 go 指令中指定的版本的前一个版本所需的校验和。因此,go 1.17 的模块包括 Go 1.16 所加载的完整模块图所需的校验和,但 go 1.18 的模块将只包括 Go 1.17 所加载的修剪模块图所需的校验和。可以使用-compat标志来覆盖默认版本(例如,在go 1.17模块中更积极地修剪go.sum文件)。
更多细节参见设计文档。
Lazy module loading 延迟模块加载
为模块图修剪增加的更全面的 requirements 也使得在模块内工作时可以进行另一种优化。如果主模块是在go 1.17或更高版本,go命令会避免加载完整的模块图,直到(或除非)需要它。相反,它只加载主模块的go.mod文件,然后尝试只使用这些 requirements 来加载要构建的包。如果在这些 requirements中没有找到要导入的包(例如,主模块之外的包的测试依赖项),那么模块图的其余部分将被加载。
如果在不加载模块图的情况下能找到所有导入的包,go命令将只加载包含这些包的模块的go.mod文件,并将它们的requirements 与主模块的requirements 进行核对,以确保它们是本地一致的。(不一致可能是由于版本控制的合并,手工编辑,以及使用本地文件系统路径替换的模块的更改造成的)。
1.4.6 - 工作区
Workspaces 工作区
工作区是磁盘上模块的集合,在运行minimal version selection (MVS) (最小版本选择(MVS))时这些模块被用作主模块。
工作区可以在 go.work 文件中声明,该文件指定了工作区中每个模块目录的相对路径。当没有go.work文件存在时,工作区由包含当前目录的单个模块组成。
大多数处理模块的go子命令都是在由当前工作区决定的模块集合上操作的。go mod init、go mod why、go mod edit、go mod tidy、go mod vendor和go get总是在一个主模块上操作。
命令首先通过检查GOWORK环境变量来确定它是否处于工作区上下文中。如果GOWORK被设置为off,该命令将处于单模块上下文中。如果它是空的或者未提供,命令将在当前工作目录中搜索,然后在连续的父目录中搜索go.work这个文件。如果找到一个(go.work)文件,该命令将在该文件定义的工作区中操作;否则,工作区将只包括包含工作目录的模块。如果GOWORK命名一个以.work结尾的现有文件的路径,工作区模式将被启用。任何其他的值都是一个错误。你可以使用go env GOWORK命令来确定go命令正在使用哪个go.work文件。如果go命令没有进入工作区模式,go env GOWORK将为空。
go.work files
工作区是由一个名为go.work的UTF-8编码文本文件定义的。go.work文件是面向行的。每行包含一个指令,由一个关键字和参数组成。例如:
go 1.18
use ./my/first/thing
use ./my/second/thing
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
与go.mod文件一样,前导关键字可以从相邻的行中分解出来,形成一个块。
use (
./my/first/thing
./my/second/thing
)
go命令提供了几个操作go.work文件的子命令。go work init创建新的go.work文件。go work use向go.work文件添加模块目录。go work edit执行低级别的编辑。Go 程序可以使用 golang.org/x/mod/modfile 包,以编程方式进行相同的更改。
Lexical elements 词汇元素
go.work文件中的词汇元素的定义方式与go.mod 文件完全相同。
Grammar 语法
go.work的语法由下面使用Extended Backus-Naur Form (EBNF)来指定。有关 EBNF 语法的详细信息,请参见 Go 语言规范中的标记法部分。
GoWork = { Directive } .
Directive = GoDirective |
UseDirective |
ReplaceDirective .
换行符、标识符和字符串分别用newline、ident和string表示。
模块路径和版本用ModulePath和Version来表示。模块路径和版本的指定方式与go.mod文件的指定方式完全相同。
ModulePath = ident | string . /* see restrictions above */
Version = ident | string . /* see restrictions above */
go directive
在一个有效的go.work文件中需要一个go指令。版本必须是有效的Go发布版本:一个正整数后跟一个点和一个非负整数(例如,1.18,1.19)。
go指令表示go.work文件所要使用的go工具链版本。如果go.work文件的格式发生了变化,未来版本的工具链将根据其指示的版本来解释该文件。
一个go.work文件最多只能包含一个go指令。
GoDirective = "go" GoVersion newline .
GoVersion = string | ident . /* valid release version; see above */
示例:
go 1.18
use directive
use将磁盘上的一个模块添加到工作区的主模块集合中。它的参数是包含该模块的go.mod文件的目录的相对路径。use指令并不添加包含在其参数目录下的子目录中的模块。这些模块可以由包含其go.mod文件的目录在单独的use指令中添加。=>仍有疑问??这里应该是“require指令中添加吧”??
UseDirective = "use" ( UseSpec | "(" newline { UseSpec } ")" newline ) .
UseSpec = FilePath newline .
FilePath = /* platform-specific relative or absolute file path */
示例:
use ./mymod // example.com/mymod
use (
../othermod
./subdir/thirdmod
)
replace directive
与go.mod文件中的replace指令类似,go.work文件中的replace指令用其他地方的内容替换一个模块的特定版本,或一个模块的所有版本。go.work中的通配符替换可以覆盖go.mod文件中特定版本的replace。
go.work文件中的replace指令会覆盖工作区模块中相同模块或模块版本的任何替换。
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
示例:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
1.4.7 - 与非模块存储库的兼容性
Compatibility with non-module repositories 与非模块存储库的兼容性
为了确保从GOPATH到模块的平稳过渡,go命令可以通过添加go.mod文件,从尚未迁移到模块的存储库中以模块感知模式下载和构建包。
当 go 命令直接从存储库中下载一个给定版本的模块时,它会查找模块路径的存储库 URL,将该版本映射到存储库中的一个修订版,然后提取该修订版的存储库存档。如果模块的路径等于存储库的根路径,且存储库的根目录不包含go.mod文件,那么go命令会在模块缓存中合成一个go.mod文件,其中包含一个module 指令,而不包含其他内容。由于合成的go.mod文件不包含其依赖项的require指令,依赖这些模块的其他模块可能需要额外的require指令(带有// indirect),以确保每个依赖项在每次构建时都以相同的版本被获取。
当go命令从proxy(代理)下载模块时,它将go.mod文件与其余模块内容分开下载。如果原始模块没有go.mod文件,那么代理将提供一个合成的go.mod文件。
+incompatible versions
在主版本2或更高版本发布的模块必须在其模块路径上有一个匹配的major version suffix(主版本后缀)。例如,如果一个模块是以v2.0.0发布的,其路径必须有/v2的后缀。这允许 go 命令可以将一个项目的多个主版本视为不同的模块,即使它们是在同一个存储库中开发的。
主版本后缀的需求是在go命令添加模块支持时引入的,许多存储库在这之前已经将版本标记为主版本2或更高。为了保持与这些存储库的兼容性,go命令在没有go.mod文件的主版本2或更高的版本上添加一个+incompatible后缀。+incompatible表示某个版本与主版本号较低的版本属于同一个模块;因此,go命令可能会自动升级到较高的+incompatible版本,即使它可能会破坏构建。
考虑下面的示例需求:
require example.com/m v4.1.2+incompatible
版本v4.1.2+incompatible指的是提供example.com/m模块的存储库中的semantic version tag(语义版本标签)v4.1.2。该模块必须在repository root path(存储库根目录)中(也就是说,存储库根路径也必须是example.com/m),并且不能有go.mod文件存在。该模块可能有主版本号较低的版本,如v1.5.2,go命令可能会自动升级这些版本到v4.1.2+incompatible(有关升级如何工作的信息,请参见最小版本选择(MVS))。
在版本v2.0.0被标记后迁移到模块的存储库通常应该发布一个新的主版本。在上面的例子中,作者应该创建一个路径为 example.com/m/v5 的模块,并发布 v5.0.0 版本。作者还应该更新模块中包的导入,使用前缀 example.com/m/v5 而不是 example.com/m。更详细的例子请参见Go Modules: v2 and Beyond(Go模块:v2及以后)。
注意 +incompatible 后缀不应该出现在存储库的标签上;像 v4.1.2+incompatible 这样的标签会被忽略。这个后缀只出现在 go 命令所使用的版本中。关于版本和标签之间的区别,请参见Mapping versions to commits(将版本映射到提交)。
还要注意的是,+incompatible 后缀可能会出现在pseudo-versions(伪版本)中。例如,v2.0.1-20200722182040-012345abcdef+incompatible可能是一个有效的伪版本。
Minimal module compatibility 最小的模块兼容性
以主版本2或更高版本发布的模块需要在其module path(模块路径)上有一个major version suffix(主版本后缀)。该模块可以在其存储库中的major version subdirectory(主版本子目录)下开发,也可以不在其中开发。这对于在构建 GOPATH 模式时在模块中导入包的包有一定的影响。
通常在 GOPATH 模式下,包被存储在与其repository’s root path(存储库的根路径)相匹配的目录中,该根路径与其在存储库中的目录相关联。例如,存储库中根路径 example.com/repo在子目录 sub 的包将被存储在 $GOPATH/src/example.com/repo/sub,并将被导入为 example.com/repo/sub。
对于带有主版本后缀的模块,人们可能希望在$GOPATH/src/example.com/repo/v2/sub目录下找到包example.com/repo/v2/sub。这就要求在其存储库的v2子目录中开发该模块。go命令支持这一点,但不需要它(请参见Mapping versions to commits(将版本映射到提交))。
如果模块不是在主版本的子目录中开发的,那么它在GOPATH中的目录将不包含主版本后缀,并且它的包可以在没有主版本后缀的情况下被导入。在上面的示例中,可以在目录 $GOPATH/src/example.com/repo/sub 中找到该包,并被导入为 example.com/repo/sub。
这给打算在模块模式和 GOPATH 模式下构建的包带来问题:模块模式需要后缀,而 GOPATH 模式不需要。
为了解决这个问题,在Go 1.11中加入了最小模块兼容性,并向后移植到Go 1.9.7和1.10.3。当导入路径被解析为 GOPATH 模式下的目录时:
(a)当解析形式为$modpath/$vn/$dir的导入时,其中:
$modpath是有效的模块路径。$vn是主版本后缀。$dir可能是一个是空的子目录。
(b)如果以下所有情况均为 true:
-
$modpath/$vn/$dir包不存在于任何相关的vendor目录中。 -
go.mod文件与导入文件位于同一目录中,或者位于$GOPATH/src根目录以下的任何父目录中。 -
不存在
$GOPATH[i]/src/$modpath/$vn/$suffix目录(对于任何根$GOPATH[i])。 -
文件
$GOPATH[d]/src/$modpath/go.mod存在(对于某个根$GOPATH[d]),并且声明模块路径为$modpath/$vn。
(c)那么将$modpath/$vn/$dir的导入解析到目录$GOPATH[d]/src/$modpath/$dir。
这个规则允许已经迁移到模块的包在GOPATH模式下构建时导入其他已经迁移到模块的包,即使没有使用主版本子目录。
1.4.8 - 具有模块感知的命令
Module-aware commands 具有模块感知的命令
大多数 go 命令可以在模块感知模式或 GOPATH 模式下运行。在模块感知模式下,go命令使用go.mod文件来查找版本依赖项,它通常从module cache(模块缓存)中加载包,如果缺少模块则下载模块。在GOPATH模式下,go命令忽略了模块;它在vendor 目录和GOPATH中寻找依赖项。
从Go 1.16开始,无论go.mod文件是否存在,模块感知模式都是默认启用的。在较低的版本中,当当前目录或任何父目录中存在go.mod文件时,模块感知模式被启用。
模块感知模式可以通过GO111MODULE环境变量来控制,该变量可以设置为on、off、或auto。
- 如果
GO111MODULE=off,go命令会忽略go.mod文件,并在GOPATH模式下运行。 - 如果
GO111MODULE=on或未设置,则go命令在模块感知模式下运行,即使没有go.mod文件存在。并非所有命令在没有go.mod文件的情况下都能运行:参见Module commands outside a module(模块外的模块命令)。 - 如果
GO111MODULE=auto,如果当前目录或任何父目录中存在go.mod文件,go命令将以模块感知模式运行。在Go 1.15及更低版本中,这是默认行为。即使没有go.mod文件,go mod子命令和带version query(版本查询)的go install也会以模块感知模式运行。
在模块感知模式下,GOPATH 在构建过程中不再定义导入的含义,但它仍然存储下载的依赖项(在 GOPATH/pkg/mod 中;参见Module cache(模块缓存))和安装的命令(在 GOPATH/bin 中,除非设置了 GOBIN)。
Build commands 构建命令
所有加载包信息的命令都是模块感知的。这包括:
go buildgo fixgo generatego getgo installgo listgo rungo testgo vet
在模块感知模式下运行时,这些命令使用go.mod文件来解释命令行中列出的或写在Go源文件中的导入路径。这些命令接受以下所有模块命令通用的标志:
(a)-mod标志控制go.mod是否可以自动更新以及是否使用vendor目录。
-mod=mod告诉go命令忽略vendor目录并automatically update(自动更新)go.mod,例如,当没有任何已知模块提供导入的包时。-mod=readonly告诉go命令忽略vendor目录,并在go.mod需要更新时报告一个错误。-mod=vendor告诉go命令使用vendor目录。在这种模式下,go命令将不使用网络或模块缓存。- 默认情况下,如果
go.mod中的go 版本是1.14或更高,并且有一个vendor目录,go命令就会像使用-mod=vendor一样行事。否则,go命令会像使用了-mod=readonly一样行事。
(b)-modcacherw标志指示go命令以读写权限在模块缓存中创建新目录,而不是让它们成为只读。当这个标志被一致地使用时(通常是通过在环境中设置GOFLAGS=-modcacherw或运行go env -w GOFLAGS=-modcacherw),模块缓存可以用rm -r等命令删除,而不必先更改权限。go clean -modcache命令可以用来删除模块缓存,无论是否使用了-modcacherw。
(c)-modfile=file.mod标志指示go命令读取(也可能写入)一个替代文件,而不是模块根目录下的go.mod。该文件的名称必须以.mod结尾。一个名为go.mod的文件必须仍然存在,以便确定模块根目录,但它不会被访问。当指定-modfile时,也会使用另一个go.sum文件:它的路径是通过修剪.mod扩展名和附加.sum从-modfile标志中得出的。
Vendoring
当使用模块时,go命令通常通过将模块从它们的源下载到模块缓存中,然后从这些下载的副本中加载包来满足依赖项。Vendoring 可以用来允许与旧版本的Go互操作,或者确保所有用于构建的文件都存储在单个文件树中。
go mod vendor命令在主模块的根目录下构建一个名为vendor的目录,其中包含主模块中构建和测试包所需的所有包的副本。那些只被主模块外的包测试所导入的包不包括在内。与go mod tidy和其他模块命令一样,在构建vendor目录时,除了ignore之外,不考虑其他的build constraints(构建约束)。
go mod vendor还创建了包含供应商包列表和从中复制包的模块版本的vendor/modules.txt文件。启用 vendoring 时,这个清单被用作模块版本信息的来源,正如 go list -m 和 go version -m 所报告的那样。当 go 命令读取 vendor/modules.txt 时,它会检查模块的版本是否与 go.mod 一致。如果go.mod在vendor/modules.txt生成后发生了变化,go命令将报告一个错误。应再次运行go mod vendor以更新vendor目录。
如果vendor目录存在于主模块的根目录中,如果主模块的go.mod文件中的 go 版本是1.14或更高,它将被自动使用。要显式地启用 vendoring 功能,请在调用go命令时使用-mod=vendor标志。要禁用 vendoring,请使用 -mod=readonly 或 -mod=mod标志。
启用vendoring后,像go build和go test这样的build commands(构建命令)会从vendor目录中加载包,而不是访问网络或本地模块缓存。go list -m命令只打印go.mod中列出的模块信息。当启用 vendoring 时,go mod命令(如go mod download 和 go mod tidy)的工作方式不会有所不同,它们仍然会下载模块和访问模块缓存。 当启用 vendoring 时,go get也不会有不同工作方式。
与在GOPATH模式下 vendoring 不同的是,go命令忽略了主模块根目录以外的 vendor 目录。此外,由于不使用其他模块中的 vendor 目录,go命令在构建module zip files(模块压缩文件)时不包括vendor 目录(但请参阅已知 bugs #31562和#37397)。
go get
使用方法:
go get [-d] [-t] [-u] [build flags] [packages]
示例:
# Upgrade a specific module.
# 升级特定模块。
$ go get golang.org/x/net
# Upgrade modules that provide packages imported by packages in the main module.
# 升级被主模块中包所导入的包的模块。
$ go get -u ./...
# Upgrade or downgrade to a specific version of a module.
# 升级或降级到模块的特定版本。
$ go get golang.org/x/text@v0.3.2
# Update to the commit on the module's master branch.
# 更新到模块的主分支上的提交。
$ go get golang.org/x/text@master
# Remove a dependency on a module and downgrade modules that require it
# to versions that don't require it.
# 移除模块上的依赖项,并将需要它的模块降级为不需要它的版本。
$ go get golang.org/x/text@none
go get命令更新main module (主模块)的go.mod文件中的模块依赖项,然后构建并安装命令行中列出的包。
第一步是确定要更新哪些模块。go get接受包、包模式和模块路径的列表作为参数。如果指定了包参数,go get将更新提供该包的模块。如果指定了包模式(例如,all或带有...通配符的路径),go get 将该模式扩展为一组包,然后更新提供包的模块。如果一个参数命名了一个模块而不是一个包(例如,模块 golang.org/x/net 在其根目录下没有包),go get 将会更新模块,但不会构建包。如果没有指定参数,go get的行为就像指定了.(当前目录下的包);这可以和-u标志一起使用,以更新提供导入包的模块。
每个参数可以包括一个版本查询后缀,表示所需的版本,如go get golang.org/x/text@v0.3.0。版本查询后缀由@符号和version query(版本查询)组成,后者可以表示一个特定的版本(v0.3.0),一个版本前缀(v0.3),一个分支或标签名称(master),一个修订版(1234abcd),或者一个特殊的查询latest,upgrade,patch,或none。如果没有给出版本,go get使用@upgrade查询。
一旦go get将参数解析为特定的模块和版本,go get将在主模块的go.mod文件中添加、更改或移除require 指令,以确保这些模块在未来保持所需的版本。注意,go.mod文件中的要求版本是最小版本,可能会随着新的依赖项的加入而自动增加。参见Minimal version selection (MVS)(最小版本选择(MVS)),了解如何通过模块感知命令选择版本和解决冲突的细节。
当命令行上命名的模块被添加、升级或降级时,如果命名的模块的新版本需要其他更高版本的模块,其他模块可能被升级。例如,假设模块example.com/a升级到v1.5.0版本,该版本需要v1.2.0版本的模块example.com/b。如果模块example.com/b目前需要v1.1.0版本,go get example.com/a@v1.5.0也会将example.com/b升级到v1.2.0。
go get upgrading a transitive requirement
go get 升级一个过渡性需求
当命令行上命名的模块被降级或移除时,其他模块可能会被降级。继续上面的例子,假设模块 example.com/b 被降级到 v1.1.0。模块 example.com/a 也将被降级为需要v1.1.0的 example.com/b 的版本或更低的版本。
go get downgrading a transitive requirement
go get 降级一个过渡性需求
可以使用版本后缀@none 移除模块需求。这是一种特殊的降级。依赖于被移除模块的模块将被降级或根据需要被移除。模块需求可以被移除,即使它的一个或多个包被主模块的包所导入。在这种情况下,下一个构建命令可能会添加一个新的模块需求。
如果需要两个不同的版本的模块(在命令行参数中明确指定或为了满足升级和降级),go get将报告一个错误。
在go get选择了一组新的版本后,它会检查任何新选择的模块版本或任何在命令行上命名的提供包的模块是否被retracted(撤回)或deprecated(废弃)。go get为它发现的每个撤回的版本或废弃的模块打印一个警告。go list -m -u all可以用来检查所有依赖项中的撤回和废弃。
After go get updates the go.mod file, it builds the packages named on the command line. Executables will be installed in the directory named by the GOBIN environment variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set.
在go get更新go.mod文件后,它将构建命令行上指定的包。可执行文件将被安装在由GOBIN环境变量命名的目录中,如果没有设置GOBIN环境变量,则默认为$GOPATH/bin或$HOME/go/bin。=>仍有疑问??这里应该是:“如果没有设置GOBIN环境变量”。
go get支持以下标志:
-d标志告诉go get不要构建或安装包。当使用-d时,go get将只管理go.mod中的依赖项。在没有-d的情况下使用go get来构建和安装包已经被废弃了(从Go 1.17开始)。在 Go 1.18 中,-d将永远被启用。-u标志告诉go get升级提供直接或间接由命令行上命名的包导入的模块。由-u选择的每个模块将被升级到其最新版本,除非它已经被要求在一个更高的(预发布版)版本。-u=patch标志(不是-u patch)也告诉go get升级依赖项,但go get将把每个依赖项升级到最新的修订版本(类似于@patch版本查询)。-t标志告诉go get考虑构建命令行上命名的包的测试所需的模块。当-t和-u一起使用时,go get也会更新测试依赖。- 不应再使用
-insecure标志。它允许go get解析自定义导入路径,并使用不安全的方案(如HTTP)从存储库和模块代理处获取。GOINSECUREenvironment variable(环境变量)提供了更精细的控制,应该使用它来代替。
从 Go 1.16 开始,go install 是推荐用于构建和安装程序的命令。当与版本后缀一起使用时(如@latest或@v1.4.6),go install以模块感知模式构建包,忽略当前目录或任何父目录中的go.mod文件(如果有的话)。
go get 更加专注于管理 go.mod 中的需求。-d 标志已被弃用,在 Go 1.18 中,它将一直被启用。
go install
使用方法:
go install [build flags] [packages]
示例:
# Install the latest version of a program,
# ignoring go.mod in the current directory (if any).
# 安装一个程序的最新版本。忽略当前目录中的 go.mod(如果有的话)。
$ go install golang.org/x/tools/gopls@latest
# Install a specific version of a program.
# 安装一个特定版本的程序。
$ go install golang.org/x/tools/gopls@v0.6.4
# Install a program at the version selected by the module in the current directory.
# 在当前目录下安装一个由模块选择的版本的程序。
$ go install golang.org/x/tools/gopls
# Install all programs in a directory.
# 在一个目录中安装所有程序。
$ go install ./cmd/...
The go install command builds and installs the packages named by the paths on the command line. Executables (main packages) are installed to the directory named by the GOBIN environment variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set. Executables in $GOROOT are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN. Non-executable packages are built and cached but not installed.
go install命令建立并安装由命令行上的路径命名的包。可执行文件(main包)被安装到由GOBIN环境变量命名的目录中,如果没有设置GOPATH环境变量,则默认为$GOPATH/bin或$HOME/go/bin。$GOROOT中的可执行程序会被安装到$GOROOT/bin或$GOTOOLDIR中,而不是$GOBIN。非可执行包会被构建和缓存,但不会安装。=>仍有疑问??这里应该是:“如果没有设置GOBIN环境变量”?
从Go 1.16开始,如果参数有版本后缀(如@latest或@v1.0.0),go install会以模块感知模式构建包,忽略当前目录或任何父目录中的go.mod文件(如果有)。这对于安装可执行文件而不影响主模块的依赖项很有用。
为了消除在构建中使用哪些模块版本的歧义,参数必须满足以下限制:
(a)参数必须是包路径或包模式(带有"...“通配符)。它们不能是标准包(如fmt)、元模式(std、cmd、all)或相对或绝对文件路径。
(b)所有参数必须具有相同的版本后缀。不允许使用不同的查询,即使它们引用的是同一个版本。
(c)所有参数必须引用同一模块中同一版本的包。
(d)包路径参数必须指的是main包。模式参数将只匹配main包。
(e)没有模块被认为是主模块。
- 如果命令行中包含包的模块有一个
go.mod文件,那么它就不能包含指令(replace和exclude),如果它是主模块,那么这些指令会导致对它的解释不同。 - 该模块不能要求自己有更高的版本。
- 在任何模块中都不使用
vendor目录。(vendor目录不包括在module zip files(模块压缩文件)中,所以go install不会下载它们)。
有关支持的版本查询语法,请参见Version queries(版本查询)。Go 1.15 及以下版本不支持在 go install 中使用版本查询。
如果参数没有版本后缀,go install 可能以模块感知模式或 GOPATH 模式运行,这取决于 GO111MODULE 环境变量和 go.mod 文件的存在。详情请参见模块感知命令。如果启用了模块感知模式,go install 在主模块的上下文中运行,这可能与包含正在安装的包的模块不同。
go list -m
使用方法:
go list -m [-u] [-retracted] [-versions] [list flags] [modules]
示例:
$ go list -m all
$ go list -m -versions example.com/m
$ go list -m -json example.com/m@latest
-m标志使go list列出模块而不是包。在这种模式下,go list的参数可以是模块、模块模式(包含...通配符)、版本查询,或者特殊模式all(它匹配build list(构建列表)中的所有模块)。如果没有指定参数,main module(主模块)将被列出。
当列出模块时,-f标志仍然指定应用于Go 结构体的格式模板,但现在是一个Module结构体:
type Module struct {
Path string // module path
Version string // module version
Versions []string // available module versions
Replace *Module // replaced by this module
Time *time.Time // time version was created
Update *Module // available update (with -u)
Main bool // is this the main module?
Indirect bool // module is only indirectly needed by main module
Dir string // directory holding local copy of files, if any
GoMod string // path to go.mod file describing module, if any
GoVersion string // go version used in module
Retracted []string // retraction information, if any (with -retracted or -u)
Deprecated string // deprecation message, if any (with -u)
Error *ModuleError // error loading module
}
type ModuleError struct {
Err string // the error itself
}
默认输出是打印模块路径,然后是版本和替换信息(如果有)。例如,go list -m all可能会打印:
example.com/main/module
golang.org/x/net v0.1.0
golang.org/x/text v0.3.0 => /tmp/text
rsc.io/pdf v0.1.1
Module结构体有一个String方法用来格式化这一行的输出,因此默认格式相当于-f '{{.String}}'。
注意,当一个模块被替换时,它的Replace字段描述了替换的模块,它的Dir字段被设置为替换模块的源代码(如果存在的话)。(也就是说,如果Replace不是nil,那么Dir被设置为Replace.Dir,不能访问被替换的源代码。)
-u 标志增加了关于可用升级的信息。当一个给定模块的最新版本比当前版本新时,list -u将模块的Update字段设置为较新模块的信息。list -u还打印当前选择的版本是否retracted(被撤回),以及该模块是否deprecated(被废弃)。模块的 String 方法通过在当前版本后面的方括号中格式化较新的版本来表示可用的升级。例如,go list -m -u all可能打印:
example.com/main/module
golang.org/x/old v1.9.9 (deprecated)
golang.org/x/net v0.1.0 (retracted) [v0.2.0]
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 [v0.1.2]
(对于工具来说,go list -m -u -json all 可能更方便解析。)
-versions 标志使 list 将模块的 Versions 字段设置为该模块的所有已知版本的列表,按照语义版本划分从低到高排序。该标志还改变了默认的输出格式,以显示模块路径后跟空格分隔的版本列表。除非同时指定了-retracted标志,否则这个列表中会省略掉被撤回的版本。
-retracted 标志指示 list 在用 -versions 标志打印的列表中显示撤回的版本,并在解析版本查询时考虑撤回的版本。例如,go list -m -retracted example.com/m@latest 显示了 example.com/m 模块的最高发布或预发布版本,即使该版本已被撤回。retract 指令和废弃的内容会以该版本从 go.mod 文件加载。-retracted标志是在Go 1.16中加入的。
模板函数module接收单个字符串参数,该参数必须是模块路径或查询,并将指定的模块作为Module结构体返回。如果发生错误,结果将是一个带有非nilError字段的Module结构体。
go mod download
使用方法:
go mod download [-json] [-x] [modules]
示例:
$ go mod download
$ go mod download golang.org/x/mod@v0.2.0
go mod download命令将命名的模块下载到module cache(模块缓存)中。参数可以是选择主模块的依赖项的模块路径或模块模式,也可以是path@version形式的版本查询。如果没有参数,download适用于主模块的所有依赖项。
go命令会在正常执行过程中根据需要自动下载模块。go mod download命令主要用于预先填充模块缓存或加载由module proxy(模块代理)提供的数据。
默认情况下,download不向标准输出写入任何内容。它将进度信息和错误打印到标准错误中。
-json标志使download将一连串的JSON对象打印到标准输出,描述每个下载的模块(或失败),对应于这个Go结构体:
type Module struct {
Path string // module path
Query string // version query corresponding to this version
Version string // module version
Error string // error loading module
Info string // absolute path to cached .info file
GoMod string // absolute path to cached .mod file
Zip string // absolute path to cached .zip file
Dir string // absolute path to cached source root directory
Sum string // checksum for path, version (as in go.sum)
GoModSum string // checksum for go.mod (as in go.sum)
Origin any // provenance of module
Reuse bool // reuse of old module info is safe
}
-x 标志使download将download执行的命令打印到标准错误中。
go mod edit
使用方法:
go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
示例:
# Add a replace directive.
# 添加一个替换指令。
$ go mod edit -replace example.com/a@v1.0.0=./a
# Remove a replace directive.
# 移除一个替换指令。
$ go mod edit -dropreplace example.com/a@v1.0.0
# Set the go version, add a requirement, and print the file
# instead of writing it to disk.
# 设置go 版本,添加一个需求,并打印文件,而不是将其写入磁盘。
$ go mod edit -go=1.14 -require=example.com/m@v1.0.0 -print
# Format the go.mod file.
# 格式化 go.mod 文件
$ go mod edit -fmt
# Format and print a different .mod file.
# 格式化并打印一个不同的.mod文件。
$ go mod edit -print tools.mod
# Print a JSON representation of the go.mod file.
# 打印go.mod文件的JSON表示。
$ go mod edit -json
go mod edit命令为编辑和格式化go.mod文件提供了一个命令行界面,主要供工具和脚本使用。go mod edit只读取一个go.mod文件;它不查询其他模块的信息。默认情况下,go mod edit读写主模块的go.mod文件,但可以在编辑标志后指定一个不同的目标文件。
编辑标志指定了一连串的编辑操作。
-
-module标志更改模块的路径(go.mod文件的模块行)。 -
-go=version标志设置预期的 Go 语言版本。 -
-require=path@version和-droprequire=path标志在给定的模块路径和版本上添加和移除一个需求。注意-require会覆盖路径上的任何现有需求。这些标志主要用于理解模块图的工具。用户应该更喜欢go get path@version或go get path@none,它们会根据需要进行其他go.mod调整,以满足其他模块施加的约束。参见go get。 -
-exclude=path@version和-dropexclude=path@version标志为指定的模块路径和版本添加和移除一个排除项。请注意,如果排除已经存在,则-exclude=path@version是一个no-op。 -
-replace=old[@v]=new[@v]标志增加对给定模块路径和版本的替换。如果省略了old@v中的@v,就会添加一个左侧没有版本的替换,它适用于旧模块路径的所有版本。如果new@v中的@v被省略,新路径应该是本地模块根目录,而不是模块路径。注意,-replace覆盖了old[@v]的所有冗余替换,因此省略@v将移除对特定版本的替换。 -
-dropreplace=old[@v]标志会放弃对给定模块路径和版本的替换。如果提供了@v,就会移除具有给定版本的替换。左侧没有版本的现有替换仍然可以替换该模块。如果省略了@v,没有版本的替换将被移除。 -
-retract=version和-dropretract=version标志为给定的版本添加和移除一个撤回,这个版本可以是一个单一的版本(如v1.2.3)或一个间隔(如[v1.1.0,v1.2.0])。注意,-retract标志不能为retract指令添加理由注释。理由注释是推荐的,可以通过go list -m -u和其他命令显示。
编辑标志可以重复使用。更改是按照给出的顺序进行的。
go mod edit有额外的标志来控制其输出。
-fmt标志对go.mod文件进行重新格式化,而不做其他修改。使用或重写go.mod文件的任何其他修改也暗示了这种重新格式化。只有在没有指定其他标志的情况下才需要这个标志,如go mod edit -fmt。-print标志以文本格式打印最终的go.mod,而不是将其写回磁盘。-json标志以JSON格式打印最终的go.mod,而不是以文本格式写回磁盘。JSON输出对应的是这些Go类型:
type Module struct {
Path string
Version string
}
type GoMod struct {
Module ModPath
Go string
Require []Require
Exclude []Module
Replace []Replace
Retract []Retract
}
type ModPath struct {
Path string
Deprecated string
}
type Require struct {
Path string
Version string
Indirect bool
}
type Replace struct {
Old Module
New Module
}
type Retract struct {
Low string
High string
Rationale string
}
注意,这只是描述go.mod文件本身,而不是间接引用的其他模块。要想知道构建中可用的全部模块,请使用go list -m -json all。参见go list -m。
例如,一个工具可以通过解析go mod edit -json的输出来获得作为数据结构的go.mod文件,然后可以通过调用go mod edit的-require、-exclude等来进行更改。
工具也可以使用golang.org/x/mod/modfile包来解析、编辑和格式化go.mod文件。
go mod graph
使用方法:
go mod graph [-go=version]
go mod graph命令以文本形式打印module requirement graph(模块需求图)(已应用替换)。例如:
example.com/main example.com/a@v1.1.0
example.com/main example.com/b@v1.2.0
example.com/a@v1.1.0 example.com/b@v1.1.1
example.com/a@v1.1.0 example.com/c@v1.3.0
example.com/b@v1.1.0 example.com/c@v1.1.0
example.com/b@v1.2.0 example.com/c@v1.2.0
模块图中的每个顶点代表一个模块的特定版本。图中的每条边代表对一个最小版本的依赖项的需求。
go mod graph 打印图中的边,每行一个。每行有两个空格分隔的字段:一个模块版本及其一个依赖项。每个模块版本是以path@version的形式标识的。主模块没有@version后缀,因为它没有版本。
-go 标志使 go mod graph 报告由给定 Go 版本加载的模块图,而不是 go.mod 文件中 go 指令指示的版本。
参见Minimal version selection (MVS)(最小版本选择(MVS))以了解更多关于如何选择版本的信息。参见 go list -m 以打印选定的版本,以及 go mod why 以了解为什么需要某个模块。
go mod init
使用方法:
go mod init [module-path]
示例:
go mod init
go mod init example.com/m
go mod init命令在当前目录下初始化并写入一个新的go.mod文件,实际上是在当前目录下创建一个新模块。这个go.mod文件必须事先不存在。
init接受一个可选参数,即新模块的module path(模块路径)。关于选择模块路径的说明,见Module paths(模块路径)。如果省略了模块路径参数,init将尝试使用.go文件中的导入注释、vendoring 工具配置文件和当前目录(如果在GOPATH)来推断模块路径。
如果 vendoring 工具的配置文件存在,init将尝试从其中导入模块需求。init 支持以下配置文件:
GLOCKFILE(Glock)Godeps/Godeps.json(Godeps)Gopkg.lock(dep)dependencies.tsv(godeps)glide.lock(glide)vendor.conf(trash)vendor.yml(govend)vendor/manifest(gvt)vendor/vendor.json(govendor)
vendoring 工具的配置文件不可能总是以完美的保真度进行翻译。例如,如果同一存储库中的多个包以不同的版本被导入,而存储库只包含一个模块,那么导入的go.mod只能要求该模块的一个版本。你可能希望运行 go list -m all 来检查构建列表中的所有版本,并运行 go mod tidy 来添加缺失的需求和移除未使用的需求。
go mod tidy
使用方法:
go mod tidy [-e] [-v] [-go=version] [-compat=version]
go mod tidy确保go.mod文件与模块的源代码匹配。它添加任何缺失的模块需求,以构建当前模块的包和依赖项,并移除不提供任何相关包的模块的需求。它还会在go.sum中添加任何缺失的条目,并移除不必要的条目。
-e 标志(在 Go 1.16 中加入)使 go mod tidy 在加载包时遇到错误的情况下仍然尝试继续。
-v标志使go mod tidy将移除模块的信息打印到标准错误中。
go mod tidy的工作方式是以递归方式加载main module(主模块)中的所有包和它们导入的所有包。这包括由测试导入的包(包括其他模块中的测试)。go mod tidy的行为就像所有的构建标签都是启用的,所以它会考虑特定平台的源文件和需要自定义构建标签的文件,即使这些源文件通常不会被构建。有一个例外:ignore构建标签没有被启用,所以具有//+build ignore构建约束的文件将不会被考虑。注意,go mod tidy不会考虑主模块中名为testdata的目录或名称以.或_开头的包,除非这些包被其他包明确导入。
一旦go mod tidy加载了这组包,它将确保每个提供一个或多个包的模块在主模块的go.mod文件中都有require指令,或者 —— 如果主模块在go 1.16或以下 —— 被另一个require模块所需要。go mod tidy将在每个缺失的模块的最新版本上添加require(最新版本的定义参见版本查询)。
go mod tidy 也可以在 require 指令上添加或移除// indirect注释。一个// indirect注释表示一个模块没有提供被主模块中的包导入的包。(关于何时添加// indirect依赖项和注释的更多细节,请参见 require 指令)。
如果设置了 -go 标志,go mod tidy 将更新 go 指令到指定的版本,根据该版本启用或禁用module graph pruning(模块图修剪)和lazy module loading(延迟模块加载)(并根据需要添加或移除间接需求)。
默认情况下,当模块图被go指令中指定的版本之前的Go版本加载时,go mod tidy将检查所选模块的版本是否没有发生变化。兼容性检查的版本也可以通过-compat标志显式指定。
go mod vendor
使用方法:
go mod vendor [-e] [-v] [-o]
go mod vendor 命令在主模块的根目录下构建一个名为 vendor 的目录,其中包含所有支持主模块中的包的构建和测试所需的包的副本。那些只被主模块外的包测试所导入的包不包括在内。与go mod tidy和其他模块命令一样,在构建vendor目录时,不考虑其他的build constraints(构建约束)(ignore除外)。
当vendoring被启用时,go命令将从vendor目录中加载包,而不是将模块从它们的源下载到模块缓存中并使用那些下载的包。更多信息请参见Vendoring。
go mod vendor还创建vendor/modules.txt文件,该文件中包含供应商包列表和从中复制包的模块版本。启用vendoring时,这个清单被用作模块版本信息的来源,正如go list -m和go version -m所报告的。当 go 命令读取 vendor/modules.txt 时,它会检查模块的版本是否与 go.mod 一致。如果go.mod在vendor/modules.txt生成后发生了变化,那么应该再次运行go mod vendor。
注意,如果vendor目录存在,go mod vendor会在重新构造之前移除它。 不应该对vendored包进行本地修改。go命令并不检查vendor目录下的包是否被修改过,但可以通过运行go mod vendor并检查是否有修改来验证vendor目录的完整性。
-e标志(在Go 1.16中加入)使go mod vendor在加载包时遇到错误的情况下仍然尝试继续进行。
-v 标志使 go mod vendor 打印出 vendored 的模块和包的名称到标准错误。
-o标志(在Go 1.18中加入)使go mod vendor输出指定目录下的vendor树,而不是vendor。参数可以是绝对路径或相对于模块根的路径。
go mod verify
使用方法:
go mod verify
go mod verify检查存储在module cache(模块缓存)中的main module(主模块)的依赖项在下载后有没有被修改。为了进行这项检查,go mod verify对每个下载的模块.zip文件和提取的目录进行散列,然后将这些散列与模块首次下载时记录的散列进行比较。go mod verify检查构建列表中的每个模块(可以用go list -m all打印)。
如果所有的模块都没有被修改,go mod verify会打印出 “all modules verified”。否则,它会报告哪些模块被更改了,并以非零状态退出。
注意,所有的模块感知命令都会验证主模块的go.sum文件中的哈希值是否与下载到模块缓存中的模块的哈希值一致。如果go.sum文件中缺少哈希值(例如,因为模块是第一次使用),go命令会使用校验数据库验证其哈希值(除非模块路径与GOPRIVATE或GONOSUMDB匹配)。详见Authenticating modules(验证模块)。
相比之下,go mod verify会检查模块.zip文件及其提取的目录的哈希值是否与首次下载时模块缓存中记录的哈希值一致。这对检测模块下载和验证后模块缓存中文件的变化非常有用。go mod verify不下载缓存中没有的模块内容,也不使用go.sum文件来验证模块内容。然而,go mod verify可能会下载go.mod文件,以进行minimal version selection(最小的版本选择)。它将使用go.sum来验证这些文件,并可能为缺少的哈希值添加go.sum条目。
go mod why
使用方法:
go mod why [-m] [-vendor] packages...
go mod why在导入图中显示了从主模块到每个列出的包的最短路径。
输出是一个节序列,命令行上命名的每个包或模块对应一个节,用空行分隔。每个节都以#开头的注释行开始,给出目标包或模块。随后的行给出了通过导入图的路径,每行一个包。如果该包或模块没有被主模块引用,节将显示一个带圆括号的注释来说明这一事实。
示例:
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
-m标志使go mod why将其参数视为模块列表。go mod why将打印每个模块中任何包的路径。注意,即使使用了-m,go mod why也会查询包图,而不是go mod graph打印的模块图。
-vendor标志使go mod why忽略在主模块之外的包的测试中的导入(就像go mod vendor 所做的那样)。默认情况下,go mod why考虑由all模式匹配的包图。在声明go 1.16或更高版本(使用go.mod中的go 指令)的模块中,该标志在Go 1.16之后不再生效,因为all的含义更改为与go mod vendor匹配的包集合相匹配。
go version -m
使用方法:
go version [-m] [-v] [file ...]
示例:
# Print Go version used to build go.
# 打印用于构建go的Go版本。
$ go version
# Print Go version used to build a specific executable.
# 打印用于构建特定可执行文件的Go版本。
$ go version ~/go/bin/gopls
# Print Go version and module versions used to build a specific executable.
# 打印用于构建特定可执行文件的Go版本和模块版本。
$ go version -m ~/go/bin/gopls
# Print Go version and module versions used to build executables in a directory.
# 打印用于在目录中构建可执行文件的Go版本和模块版本。
$ go version -m ~/go/bin/
go version报告用于构建命令行上命名的每个可执行文件的Go版本。
如果命令行上没有指定任何文件,go version将打印它自己的版本信息。
如果指定了一个目录,go version会递归地遍历该目录,查找已识别的Go二进制文件并报告它们的版本。默认情况下,go version不报告在目录扫描期间发现的无法识别的文件。-v 标志使它报告无法识别的文件。
-m 标志使 go version 在可用时打印每个可执行文件的嵌入式模块版本信息。对于每个可执行文件,go version -m会打印一个表格,表格中的列以制表符分隔,如下图所示。
$ go version -m ~/go/bin/goimports
/home/jrgopher/go/bin/goimports: go1.14.3
path golang.org/x/tools/cmd/goimports
mod golang.org/x/tools v0.0.0-20200518203908-8018eb2c26ba h1:0Lcy64USfQQL6GAJma8BdHCgeofcchQj+Z7j0SXYAzU=
dep golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
dep golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
该表的格式在未来可能会改变。同样的信息可以从runtime/debug.ReadBuildInfo获得。
表中每一行的含义是由第一列中的字决定的。
path:用于构建可执行文件的main包的路径。mod:包含main包的模块。这些列分别是模块路径、版本和 sum。主模块有版本(devel),没有 sum。dep:提供一个或多个链接到可执行文件的包的模块。格式与mod相同。=>:替换上一行中的模块。如果替换的是本地目录,则只列出目录路径(没有版本或 sum)。如果替换的是模块版本,则会列出路径、版本和 sum,就像mod和dep一样。被替换的模块没有sum。
go clean -modcache
使用方法:
go clean [-modcache]
-modcache标志使go clean移除整个module cache(模块缓存),包括版本化依赖项的未打包的源代码。
这通常是移除模块缓存的最佳方式。默认情况下,模块缓存中的大多数文件和目录都是只读的,以防止测试和编辑者在通过authenticated(认证)后无意中改更改文件。不幸的是,这导致像rm -r这样的命令失败,因为如果不首先使其父目录可写,就无法移除文件。
-modcacherw标志(被go build和其他模块感知命令接受)使模块缓存中的新目录可以被写入。要将-modcacherw传递给所有的模块感知命令,请将其加入到GOFLAGS变量。GOFLAGS可以在环境中设置,也可以用go env -w设置。例如,下面的命令会永久地设置它:
go env -w GOFLAGS=-modcacherw
-modcacherw应该谨慎使用;开发者应该注意不要对模块缓存中的文件进行更改。 go mod verify可以用来检查缓存中的文件是否与主模块的go.sum文件中的哈希值匹配。
Version queries
有一些命令允许你使用版本查询来指定模块的版本,版本查询出现在命令行中模块或包路径后面的@字符之后。
示例:
go get example.com/m@latest
go mod download example.com/m@master
go list -m -json example.com/m@e3702bed2
版本查询可以是以下的一种:
- 完全指定的语义版本,例如
v1.2.3,它选择一个特定的版本。语法参见 Versions(版本)。 - 语义版本前缀,例如
v1或v1.2,它选择带有该前缀的最高可用版本。 - 语义上的版本比较,例如
<v1.2.3或>=v1.5.6,它选择与比较目标最接近的可用版本(对于>和>=来说是最低版本,而对于<和<=来说是最高版本)。 - 底层源码库的修订标识符,例如提交哈希前缀、修订标签或分支名称。如果修订版被标记为语义版本,则该查询将选择该版本。否则,这个查询会选择底层提交的一个伪版本。请注意,不能以这种方式选择名称与其他版本查询匹配的分支和标签。例如,
v2查询选择的是以v2开头的最新版本,而不是名为v2的分支。 - 字符串
latest,它选择可用的最高发布版本。如果没有发布版本,latest选择的是最高的预发布版本。如果没有标签版本,latest会选择存储库默认分支顶端的提交的伪版本。 - 字符串
upgrade,与latest类似,但如果模块当前需要的版本高于latest选择的版本(例如,预发布版本),upgrade将选择当前版本。 - 字符串
patch,它选择与当前所需版本相同的主版本号和次版本号的最新可用版本。如果当前没有需要的版本,patch相当于latest。从Go 1.16开始,go get在使用patch时要求有当前版本(但-u=patch标志没有这个要求)。
除了对特定命名的版本或修订版的查询外,所有的查询都考虑由go list -m -versions(见go list -m)报告的可用版本。这个列表只包含带标签的版本,不包含伪版本。不考虑主模块的 go.mod 文件中的exclude 指令所禁止的模块版本 。除了在go list -m中使用-retracted标志以及在加载retract指令时,go.mod文件中的retract指令所涵盖的版本也会被忽略。同一模块的latest版本的go.mod文件中的retract 指令覆盖的版本也会被忽略,除非-retract标志与go list -m 一起使用,以及加载retract指令时除外。
发布版本优先于预发布版本。例如,如果有v1.2.2和v1.2.3-pre两个版本,latest的查询会选择v1.2.2,尽管v1.2.3-pre的版本更高。<v1.2.4的查询也会选择v1.2.2,即使v1.2.3-pre更接近v1.2.4。如果没有发行版或预发行版,latest、upgrade和patch查询将选择存储库默认分支顶端的提交的伪版本。其他查询将报告错误。
Module commands outside a module 模块外的模块命令
模块感知的 go 命令通常在工作目录或父目录下的 go.mod 文件所定义的main module(主模块)上下文中运行。有些命令可以在没有go.mod文件的情况下以模块感知模式运行,但大多数命令工作方式不同,或者在没有 go.mod 文件时报告错误。
关于启用和禁用模块感知模式的信息,请参见模块感知命令。
go build 、go doc 、go fix、 go fmt 、go generate、 go install、 go list 、go run、 go test 、go vet:只有标准库中的包和在命令行上指定为.go文件的包才能被加载、导入和构建。来自其他模块的包不能被构建,因为没有地方可以记录模块需求并确保确定性的构建。
go get:包和可执行文件可以像往常一样被构建和安装。注意,当go get在没有go.mod文件的情况下运行时,没有主模块,所以replace和exclude指令不被应用。
go list -m:大多数参数都需要显式的版本查询,除非使用 -versions 标志。
go mod download:大多数参数都需要显式的版本查询。
go mod edit:需要一个显式的文件参数。
go mod graph 、go mod tidy、 go mod vendor 、go mod verify 、go mod why:这些命令需要一个go.mod文件,如果没有这个文件,将报告错误。
go work init
使用方法:
go work init [moddirs]
init在当前目录下初始化并写入一个新的go.work文件,实际上是在当前目录下创建一个新的工作区。
go work init可以选择接受工作区模块的路径作为参数。如果省略该参数,将创建一个没有模块的空工作区。
每个参数路径都被添加到go.work文件中的use 指令中。当前的go版本也将在go.work文件中列出。
go work edit
使用方法:
go work edit [editing flags] [go.work]
go work edit 命令为编辑 go.work 提供了一个命令行界面,主要供工具或脚本使用。它只读取go.work,并不查询相关模块的信息。如果没有指定文件,edit 会在当前目录及其父目录中寻找一个go.work文件。
编辑标志指定了一系列的编辑操作。
-fmt标志对go.work文件进行重新格式化,而不做其他修改。使用或重写go.work文件的任何其他修改也暗示了这种重新格式化。只有在没有指定其他标志的情况下才需要这个标志,如 “go work edit -fmt"。-use=path和-dropuse=path标志从go.work文件的模块目录组中添加和移除use指令。-replace=old[@v]=new[@v]标志添加对给定模块路径和版本的替换。如果省略old@v中的@v,就会添加一个左侧没有版本的替换,这适用于旧模块路径的所有版本。如果new@v中的@v被省略,新路径应该是本地模块根目录,而不是模块路径。注意,-replace会覆盖old[@v]的任何冗余替,因此省略@v将移除特定版本的现有替换。-dropreplace=old[@v]标志会移除对给定模块路径和版本的替换。如果省略@v,左侧没有版本的替换会被移除。-go=version标志设置预期的 Go 语言版本。
编辑标志可以重复使用。更改会按照给定的顺序应用。
go work edit有额外的标志来控制其输出:
-print标志以文本格式打印最终的go.work,而不是将其写回go.mod。-json标志以JSON格式打印最终的go.work文件,而不是将其写回go.mod。JSON输出对应的是这些Go类型:
type Module struct {
Path string
Version string
}
type GoWork struct {
Go string
Directory []Directory
Replace []Replace
}
type Use struct {
Path string
ModulePath string
}
type Replace struct {
Old Module
New Module
}
go work use
使用方法:
go work use [-r] [moddirs]
go work use命令提供了一个向 go.work 文件添加目录(可选择递归)的命令行界面。
对于命令行go.work文件中列出的每个参数目录,如果其在磁盘上存在,将在go.work文件中添加一个use 指令;如果其在磁盘上不存在,则从go.work文件中移除。
-r标志递归搜索参数目录中的模块,use命令的操作就像每个目录都被指定为参数一样:即,对于存在的目录将添加use指令,对于不存在的目录将移除use指令。
go work sync
使用方法:
go work sync
go work sync命令将工作区的构建列表同步回工作区的模块。
工作区的构建列表是用于在工作区进行构建的所有(过渡性的)依赖模块的版本集合。go work sync使用最小版本选择(MVS)算法生成该构建列表,然后将这些版本同步到工作区指定的每个模块中(使用use指令)。
一旦计算出工作区的构建列表,工作区中每个模块的go.mod文件就会被重写,与该模块相关的依赖项被升级,以匹配工作区的构建列表。请注意,最小版本选择(MVS)保证构建列表中的每个模块的版本总是与工作区模块中的版本相同或更高。
1.4.9 - 模块代理
Module proxies 模块代理
GOPROXY protocol
模块代理是一个HTTP服务器,可以响应下面指定路径的GET请求。这些请求没有查询参数,也不需要特定的头,因此即使是一个从固定文件系统(包括file:// URL)提供服务的网站也可以成为一个模块代理。
成功的HTTP响应必须有状态代码200 (OK)。遵循重定向(3xx)。状态码为4xx和5xx的响应被视为错误。错误码 404 (Not Found) 和410 (Gone)表示请求的模块或版本在代理上不可用,但可能在其他地方找到。错误响应的内容类型应该是text/plain,charset是utf-8或us-ascii。
go命令可以配置为使用GOPROXY环境变量联系代理或源码管理服务器,该环境变量接受一个代理URL列表。列表中可以包括关键词direct或off(详见Environment variables(环境变量))。列表中的元素可以用逗号(,)或管道符(|)分隔,这决定了错误回退行为。当URL后跟一个逗号时,go命令只有在出现404 (Not Found)或410 (Gone) 响应后才会回退到后面的源。当URL后跟一个管道符时,go命令在任何错误(包括超时等非HTTP错误)发生后都会回退到后面的源。这种错误处理行为让代理充当未知模块的守门员。例如,对于不在批准列表上的模块,代理可以响应403 (Forbidden)错误(请参见 Private proxy serving private modules(为私有模块提供服务的私有代理))。
下表列出了模块代理必须响应的查询。对于每个路径,$base是代理URL的路径部分,$module是模块路径,$version是版本。例如,如果代理的URL是https://example.com/mod,并且客户端正在为 v0.3.2版本的模块 golang.org/x/text 请求 go.mod 文件,那么客户端将为https://example.com/mod/golang.org/x/text/@v/v0.3.2.mod发送一个GET请求。
为了避免从不区分大小写的文件系统中提供服务时出现歧义,$module和$version元素采用大小写编码,将每个大写字母替换为感叹号后跟相应的小写字母。这允许模块 example.com/M 和 example.com/m 同时存储在磁盘上,因为前者被编码为 example.com/!m。
| Path 路径 | Description 描述 |
|---|---|
$base/$module/@v/list
以纯文本形式返回给定模块的已知版本列表,每行一个。该列表不应包括伪版本。
$base/$module/@v/$version.info
返回有关模块的特定版本的JSON格式的元数据。响应必须是与下面的GO数据结构体相对应的JSON对象:
|
|
Version字段是必须的,并且必须包含一个有效的、canonical version(经典的版本)(请参见Versions(版本))。请求路径中的$version不需要是相同的版本,甚至不需要是有效的版本;此端点可以用来查找分支名称或修订标识符的版本。但是,如果$version是一个经典的版本,其主版本与$module兼容,那么成功响应中的 Version 字段必须是相同的。
Time字段是可选的。如果存在,它必须是一个RFC 3339格式的字符串。它表示版本创建的时间。未来可能会增加更多的字段,因此保留其他的名字。
$base/$module/@v/$version.mod
返回模块的特定版本的go.mod文件。如果该模块在请求的版本中没有go.mod文件,则必须返回一个仅包含请求模块路径的module语句的文件。否则,必须返回原始的、未经修改的go.mod文件。
$base/$module/@v/$version.zip
返回包含模块特定版本内容的zip文件。有关此zip文件必须如何格式化的详细信息,请参阅Module zip files(模块zip文件)。
$base/$module/@latest
以与$base/$module/@v/$version.info相同格式返回有关模块的最新已知版本的JSON格式元数据。如果$base/$module/@v/list为空或者列出的版本不合适,则最新版本应该是go命令应该使用的模块版本。此端点是可选的,模块代理不需要实现它。
在解析模块的最新版本时,go命令将请求$base/$module/@v/list,如果没有找到合适的版本,则请求$base/$module/@latest。go命令按顺序优先选择:语义上最高的发布版本,语义上最高的预发布版本,以及时间上最新的伪版本。在Go 1.12和更早的版本中,go命令认为$base/$module/@v/list中的伪版本是预发布版本,但从Go 1.13开始不再是这样了。
模块代理必须始终为$base/$module/$version.mod和$base/$module/$version.zip查询的成功响应提供相同的内容。该内容使用go.sum 文件进行cryptographically authenticated(加密身份验证),默认情况下使用checksum database(校验和数据库)。
go命令将它从模块代理下载的大部分内容缓存在$GOPATH/pkg/mod/cache/download的模块缓存中。即使是直接从版本控制系统中下载,go命令也会合成显式的info、mod和zip文件,并将它们存储在此目录中,就像它直接从代理那里下载一样。缓存的布局与代理的URL空间相同,因此将$GOPATH/pkg/mod/cache/download服务于(或复制到)https://example.com/proxy,将可以让用户通过设置GOPROXY为https://example.com/proxy,来访问缓存的模块版本。
Communicating with proxies 与代理通信
go命令可以从module proxy(模块代理)处下载模块的源代码和元数据。GOPROXY环境变量可以用来配置go命令可以连接哪些代理,以及它是否可以直接与version control systems(版本控制系统)通信。下载的模块数据被保存在module cache(模块缓存)中。go命令只有在需要缓存中没有的信息时才会联系代理。
GOPROXY 协议部分描述了可能被发送到GOPROXY服务器的请求。不过,了解go命令何时发出这些请求也很有帮助。例如,go build遵循以下步骤:
- 通过读取
go.mod文件并执行最小版本选择(MVS)来计算build list(构建列表)。 - 读取命令行上命名的包和及其导入的包。
- 如果构建列表中的任何模块都没有提供某个包,则寻找提供该包的模块。将最新版本的模块需求添加到
go.mod,然后重新开始(这些步骤)。 - 在加载完所有内容之后构建包。
When the go command computes the build list, it loads the go.mod file for each module in the module graph. If a go.mod file is not in the cache, the go command will download it from the proxy using a $module/@v/$version.mod request (where $module is the module path and $version is the version). These requests can be tested with a tool like curl. For example, the command below downloads the go.mod file for golang.org/x/mod at version v0.2.0:
当 go 命令计算构建列表时,它为module graph(模块图)中的每个模块加载 go.mod 文件。如果go.mod文件不在缓存中,go命令将使用$module/@v/$version.mod请求(其中$module是模块路径,$version是版本)从代理中下载它。这些请求可以用curl这样的工具来测试。例如,下面的命令下载版本为v0.2.0的golang.org/x/mod的go.mod文件。
|
|
为了加载包,go命令需要提供该包的模块的源代码。模块源代码以.zip文件的形式发布,这些文件被解压缩到模块缓存中。如果模块.zip不在缓存中,go命令将使用$module/@v/$version.zip请求下载它。
|
|
注意,.mod和.zip的请求是分开的,尽管go.mod文件通常包含在.zip文件中。go命令可能需要为许多不同的模块下载go.mod文件,而.mod文件要比.zip文件小得多。此外,如果一个Go项目没有go.mod文件,代理将提供一个仅包含module 指令的合成go.mod文件。合成的go.mod文件是由go命令从version control system(版本控制系统)下载时生成的。
如果go命令需要加载一个构建列表中任何模块都没有提供的包,它将尝试查找一个提供该包的新模块。Resolving a package to a module(将包解析为模块)一节描述了这个过程。总之,go命令会请求每个可能包含该包的模块路径的最新版本信息。例如,对于包golang.org/x/net/html,go命令会试图查找golang.org/x/net/html、golang.org/x/net、golang.org/x/和golang.org等模块的最新版本。只有golang.org/x/net实际存在并提供该包,因此go命令使用该模块的最新版本。如果有多个模块提供该包,go命令将使用路径最长的模块。
当go命令请求某个模块的最新版本时,它首先发送一个$module/@v/list的请求。如果列表是空的或者没有一个返回的版本可以使用,它将发送对$module/@latest的请求。一旦选择了一个版本,go命令就会发送对$module/@v/$version.info的元数据请求。然后它可能会发送$module/@v/$version.mod和$module/@v/$version.zip请求来加载go.mod文件和源代码。
|
|
在下载一个.mod或.zip文件后,go命令会计算一个加密哈希值,并检查它是否与主模块的go.sum文件中的哈希值相匹配。如果哈希值不在go.sum中,默认情况下,go命令会从checksum database(校验数据库)中检索它。如果计算出的哈希值不匹配,go命令会报告一个安全错误,并且不会将该文件安装到模块缓存中。GOPRIVATE和GONOSUMDB环境变量可以用来禁止对特定模块的校验数据库的请求。GOSUMDB环境变量也可以被设置为off,以完全禁止对校验数据库的请求。更多信息请参见Authenticating modules(验证模块)。请注意,为.info请求返回的版本列表和版本元数据不经过身份验证,并且可能会随着时间的推移而改变。
Serving modules directly from a proxy 直接从代理向模块提供服务
大多数模块都是从版本控制存储库中开发和提供的。在direct mode(直接模式)下,go命令用版本控制工具下载这样的模块(见Version control systems(版本控制系统))。还可以直接从模块代理提供模块。这对那些希望在不暴露其版本控制服务器的情况下提供模块服务的组织以及使用go命令不支持的版本控制工具的组织来说非常有用。
当go命令以直接模式下载模块时,它首先根据模块路径用HTTP GET请求查找模块服务器的URL。它在HTML响应中查找一个名为go-import的<meta>标签。该标签的内容必须包含repository root path(存储库根路径)、版本控制系统和 URL,并以空格隔开。详见Finding a repository for a module path(查找模块路径的存储库)。
如果版本控制系统是mod,go命令使用GOPROXY 协议从给定的URL下载模块。
例如,假设go命令试图下载版本为v1.0.0的模块example.com/gopher。它向https://example.com/gopher?go-get=1发送请求。服务器使用包含以下标签的HTML文档进行响应:
|
|
根据这个响应,go命令通过发送https://modproxy.example.com/example.com/gopher/@v/v1.0.0.info、v1.0.0.mod和v1.0.0.zip的请求来下载该模块。
!!! warining “请注意”
注意,在`GOPATH`模式下,不能用`go get`下载从代理处直接提供的模块。
1.4.10 - 版本控制系统
Version control systems 版本控制系统
go命令可以直接从版本控制储存库中下载模块的源代码和元数据。从proxy(代理)下载模块通常更快,但如果代理不可用,或者代理无法访问模块的存储库(对于私有存储库经常如此),则需要直接连接到存储库。支持Git、Subversion、Mercurial、Bazaar和Fossil。版本控制工具必须安装在PATH的一个目录中,以便go命令使用它。
要从源码库而不是代理下载特定的模块,可以设置GOPRIVATE或GONOPROXY环境变量。要配置go命令直接从源码库下载所有模块,请将GOPROXY设置为direct。更多信息请参见Environment variables(环境变量)。
Finding a repository for a module path 查找模块路径的存储库
当go命令以direct模式下载模块时,它首先要定位包含该模块的存储库。
如果模块路径的末尾有一个VCS限定词(.bzr, .fossil, .git, .hg, .svn中的一个),go命令将使用该路径限定词之前的所有内容作为存储库的URL。例如,对于模块example.com/foo.git/bar,go命令使用git下载example.com/foo.git的存储库,期望在bar子目录下找到该模块。go命令将根据版本控制工具支持的协议来猜测要使用的协议。
如果模块路径没有限定词,go命令会向模块路径派生的URL发送带有?go-get=1查询字符串的HTTP GET请求。例如,对于模块golang.org/x/mod,go命令可能发送以下请求:
https://golang.org/x/mod?go-get=1 (preferred)
http://golang.org/x/mod?go-get=1 (fallback, only with GOINSECURE)
go命令跟随重定向,但会忽略响应状态码,因此服务器可能会以404或任何其他错误状态来响应。GOINSECURE环境变量可以被设置为允许回退并重定向到特定模块的未加密的HTTP。
服务器必须使用一个HTML文档来响应,该文档的<head>中包含一个<meta>标签。<meta>标签应该出现在文档的早期,以避免混淆go命令的受限解析器。特别是,它应该出现在任何原始JavaScript或CSS之前。<meta>标签必须具有以下形式:
<meta name="go-import" content="root-path vcs repo-url">
root-path 是存储库的根路径,即模块路径中与存储库根目录相对应的部分。它必须是一个前缀或与请求的模块路径完全匹配。如果不是完全匹配,则会对前缀进行另一次请求,以验证<meta>标签是否匹配。
vcs是版本控制系统。它必须是下表中所列的工具之一,或者是关键字mod,它指示go命令使用GOPROXY 协议从给定的URL下载模块。有关详细信息,请参阅 直接从代理向模块提供服务。
repo-url是存储库的URL。如果URL不包含方案(要么是因为模块路径有一个VCS限定符,要么是因为<meta>标签缺少一个方案),go命令将尝试版本控制系统支持的每一个协议。例如,对于 Git,go 命令将尝试 https:// 然后是 git+ssh://。不安全的协议(如 http:// 和 git://)只有在模块路径被 GOINSECURE 环境变量匹配的情况下才能使用。
| Name | Command | GOVCS default | Secure schemes |
|---|---|---|---|
| Bazaar | bzr |
Private only | https, bzr+ssh |
| Fossil | fossil |
Private only | https |
| Git | git |
Public and private | https, git+ssh, ssh |
| Mercurial | hg |
Public and private | https, ssh |
| Subversion | svn |
Private only | https, svn+ssh |
作为一个例子,再次考虑golang.org/x/mod。go命令向https://golang.org/x/mod?go-get=1 发送一个请求。服务器响应的是一个包含标签的HTML文档:
<meta name="go-import" content="golang.org/x/mod git https://go.googlesource.com/mod">
从这个响应来看,go 命令将使用远程 URL https://go.googlesource.com/mod 的 Git 存储库。
GitHub 和其他流行的托管服务会响应所有存储库的 ?go-get=1 查询,所以通常在这些站点托管的模块不需要进行服务器配置。
找到存储库的URL后,go命令会将存储库克隆到模块缓存中。一般来说,go命令尝试避免从存储库中获取不需要的数据。但是,实际使用的命令因版本控制系统而异,并可能随时间而改变。对于 Git 来说,go 命令可以在不下载提交的情况下列出大多数可用的版本。它通常会在不下载祖先提交的情况下获取提交,但这样做有时是必要的。
Mapping versions to commits 将版本映射到提交
go 命令可以检出存储库中特定canonical version(经典版本)的模块,比如 v1.2.3, v2.4.0-beta, 或者 v3.0.0+incompatible。每个模块版本在存储库中都应该有一个语义上的版本标签,表明哪个版本应该被检出。
如果在存储库根目录或根目录的主版本子目录中定义了模块,则每个版本标签名都等于相应的版本。例如,模块 golang.org/x/text 被定义在其存储库的根目录中,因此版本 v0.3.2 在该存储库中的标签为 v0.3.2。这对大多数模块来说都是如此。
如果模块被定义在存储库的子目录中,也就是说,模块路径中的module subdirectory(模块子目录)部分不是空的,那么每个标签名必须以模块子目录为前缀,后跟斜线。例如,模块golang.org/x/tools/gopls被定义在根路径为golang.org/x/tools的存储库的gopls子目录中。该模块的v0.4.0版本必须在该存储库中具有名为gopls/v0.4.0的标签。
语义版本标签的主版本号必须与模块路径的主版本后缀(如果有的话)一致。例如,标签v1.0.0可能属于模块example.com/mod,但不属于example.com/mod/v2,后者会有v2.0.0这样的标签。
如果没有go.mod文件,并且模块在存储库根目录中,那么主版本为v2或更高的标签可能属于没有主版本后缀的模块。这种版本用后缀+incompatible来表示。版本标签本身不能有这个后缀。参见Compatibility with non-module repositories(与非模块存储库的兼容性)。
一旦标签被创建,它就不应该被删除或改变为不同的版本。版本经过身份验证,以确保安全、可重复的构建。如果标签被修改,客户端在下载时可能会看到安全错误。即使标签被删除,其内容仍可在module proxies(模块代理)上使用。
Mapping pseudo-versions to commits 将伪版本映射到提交
go命令可以在存储库中检出特定修订版的模块,该修订版编码为pseudo-version(伪版本),如v1.3.2-0.20191109021931-daa7c04131f5。
伪版本的最后12个字符(上例中的daa7c04131f5)表示要检出存储库中的一个修订版。它的含义取决于版本控制系统。对于Git和Mercurial,这是一个提交哈希值的前缀。对于Subversion,这是一个以零填充的修订号。
在检出一个提交之前,go 命令会验证时间戳(上面的 20191109021931)是否与提交日期相符。它还会验证基本版本(v1.3.1,即上例中v1.3.2之前的版本)是否与提交的祖先的语义版本标签相对应。这些检查确保模块作者能够完全控制伪版本与其他发布版本的比较。
更多信息请参见Pseudo-versions(伪版本)。
Mapping branches and commits to versions 将分支和提交映射到版本
可以使用version query(版本查询)在特定分支、标签或修订版检出模块。
|
|
go 命令将这些名称转换为可用于最小版本选择(MVS)的canonical versions(经典版本)。MVS 依赖于对版本进行明确排序的能力。分支名称和修订版不能随着时间的推移可靠地进行比较,因为它们依赖于可能会更改的存储库结构。
如果一个修订版被标记了一个或多个语义版本标签,如v1.2.3,那么将使用最高有效版本的标签。go命令只考虑可能属于目标模块的语义版本标签;例如,对于example.com/mod/v2来说,v1.5.2标签不会被考虑,因为其主版本与模块路径的后缀不匹配。
如果一个修订版没有被贴上有效的语义版本标签,go命令将生成一个伪版本。如果修订版具有具有有效语义版本标签的祖先版本,那么最高的祖先版本将被用作伪版本基础。请参阅Pseudo-versions(伪版本)。
Module directories within a repository 存储库中的模块目录
一旦模块的存储库在特定的修订版中被检出,go命令必须找到包含该模块的go.mod文件的目录(模块的根目录)。
回顾一下,module path(模块路径)由三部分组成:存储库根路径(对应于存储库根目录)、模块子目录和主版本后缀(仅适用于以v2或更高版本发布的模块)。
对于大多数模块,模块路径等于存储库根路径,因此模块的根目录就是存储库的根目录。
模块有时会被定义在存储库的子目录下。这通常适用于具有多个组件的大型存储库,这些组件需要独立发布和版本化。这样的模块有望在子目录中找到,该目录与存储库根目录之后的模块路径部分相匹配。例如,假设模块 example.com/monorepo/foo/bar 位于根路径为 example.com/monorepo的存储库的中。它的go.mod文件必须位于foo/bar子目录中。
如果模块在主版本v2或更高版本发布,则其路径必须有一个major version suffix(主版本后缀)。带有主版本后缀的模块可以定义在两个子目录中的一个:一个带有后缀,另一个没有。例如,假设上面模块的一个新版本以example.com/monorepo/foo/bar/v2的路径发布。其go.mod文件可能位于foo/bar或foo/bar/v2中。
带有主版本后缀的子目录是主版本的子目录。它们可用于在单个分支上开发模块的多个主版本。当在不同的分支上进行多个主要版本的开发时,这可能是不必要的。然而,主版本的子目录有一个重要的特性:在GOPATH模式下,包的导入路径与GOPATH/src下的目录完全匹配。go命令在GOPATH模式下提供了最低限度的模块兼容性(参见Compatibility with non-module repositories(与非模块存储库的兼容性)),因此主版本子目录对于与GOPATH模式下构建的项目的兼容性来说并不总是必要的。不过不支持最低限度的模块兼容性的旧工具可能会有问题。
一旦go命令找到了模块根目录,它就会创建该目录内容的.zip文件,然后将该.zip文件解压缩到模块缓存中。关于.zip文件中可以包含哪些文件的细节,请参见File path and size constraints(文件路径和大小限制)。.zip文件的内容在提取到模块缓存之前是经过验证的,就像从代理下载.zip文件一样。
模块压缩文件不包括vendor目录的内容或任何嵌套模块(包含go.mod文件的子目录)。这意味着模块必须注意不要引用其目录外或其他模块中的文件。例如,//go:embed模式不能匹配嵌套模块中的文件。在文件不应包含在模块中的情况下,这种行为可以作为一种有用的变通方法。例如,如果存储库有大文件被检入testdata目录中,模块作者可以在testdata中添加一个空的go.mod文件,这样他们的用户就不需要下载这些文件。当然,这可能会减少用户测试其依赖项的覆盖率。
Special case for LICENSE files - 许可证文件的特殊情况
当go命令为不在存储库根目录下的模块创建.zip文件时,如果该模块的根目录(与go.mod并列)中没有名为LICENSE的文件,那么go命令将从存储库根目录下复制名为LICENSE的文件(如果该文件存在于同一修订版中)。
这种特殊情况允许相同的 LICENSE 文件应用于存储库中的所有模块。这仅适用于专门命名为 LICENSE 的文件,而没有像 .txt 这样的扩展名。遗憾的是,在不破坏现有模块的加密和的情况下,无法对其进行扩展;请参见Authenticating modules(认证模块)。其他工具和网站如 pkg.go.dev 可能会识别其他名称的文件。
还请注意,在创建模块.zip文件时,go命令不包括符号链接;请参见File path and size constraints(文件路径和大小限制)。因此,如果存储库的根目录中没有LICENSE文件,作者可以在子目录中定义的模块中创建许可证文件的副本,以确保这些文件包含在模块.zip文件中。
Controlling version control tools with GOVCS - 使用GOVCS控制版本控制工具
go命令能够使用git等版本控制命令下载模块,这对于去中心化的包生态系统至关重要,在这个系统中,代码可以从任何服务器导入。如果恶意服务器找到方法使调用的版本控制命令运行非预期的代码,这也是一个潜在的安全问题。
为了平衡功能和安全问题,go命令默认只使用git和hg从公共服务器下载代码。它将使用任何已知的版本控制系统从私有服务器下载代码,私有服务器定义为那些托管与GOPRIVATE环境变量匹配的包的服务器。之所以只允许使用Git和Mercurial,是因为这两个系统最关注作为不可信服务器的客户端运行的问题。相比之下,Bazaar、Fossil和Subversion主要用于可信的、经过验证的环境中,并没有被作为攻击面那样受到仔细检查。
版本控制命令的限制仅适用于使用直接版本控制访问下载代码的情况。当从代理下载模块时,go命令改用GOPROXY 协议,这是始终允许的。默认情况下,go命令使用Go模块镜像(proxy.golang.org)来下载公共模块,只有在私有模块或镜像拒绝为公共包提供服务(通常是出于法律原因)才会回退到版本控制。因此,客户端仍然可以默认访问从Bazaar、Fossil或Subversion存储库提供的公共代码,因为这些下载使用Go模块镜像,它承担了使用自定义沙箱运行版本控制命令的安全风险。
GOVCS变量可以用来更改特定模块所允许的版本控制系统。GOVCS变量适用于在模块感知模式和GOPATH模式下构建包。当使用模块时,模式与模块路径匹配。当使用 GOPATH 时,模式与版本控制库根目录对应的导入路径相匹配。
GOVCS变量的一般形式是一个用逗号分隔的pattern:vcslist规则的列表。pattern 是一个glob pattern,必须与模块或导入路径的一个或多个前导元素相匹配。vcslist是一个管道分隔的允许使用的版本控制命令的列表,或all允许使用任何已知的命令,或off不允许使用。请注意,如果模块与vcslist off时的模式相匹配,如果原服务器使用mod方案,该模块仍然可以被下载,该方案指示go命令使用GOPROXY 协议下载该模块。 应用列表中最早的匹配模式,即使后面的模式也可能匹配。
例如,请考虑:
GOVCS=github.com:git,evil.com:off,*:git|hg
在此设置下,模块或导入路径以github.com/开头的代码只能使用git;evil.com上的路径不能使用任何版本控制命令,而所有其他路径(*匹配所有)只能使用git或hg。
特殊模式public和private匹配公共和私人模块或导入路径。如果路径与GOPRIVATE变量相匹配,那么它就是私有路径;否则就是公共路径。
如果GOVCS变量中没有规则与某个特定的模块或导入路径相匹配,go命令会应用其默认规则,该规则现在可以用GOVCS标记法概括为public:git|hg,private:all。
要允许对任何包不受限制地使用任何版本控制系统,请使用:
GOVCS=*:all
要禁用所有版本控制的使用,使用:
GOVCS=*:off
go env -w 命令可以用来设置 GOVCS 变量,以便今后调用 go 命令。
GOVCS 是在 Go 1.16 中引入的。早期版本的Go可以对任何模块使用任何已知的版本控制工具。
1.4.11 - 模块zip文件
Module zip files 模块zip文件
模块版本是以.zip文件的形式发布的。很少有必要直接与这些文件互动,因为go命令会自动从module proxies(模块代理)和版本控制库中创建、下载和提取这些文件。但是,了解这些文件对了解跨平台的兼容性约束或在实现模块代理时仍然很有用。
go mod download命令下载一个或多个模块的zip文件,然后将这些文件提取到模块缓存中。根据GOPROXY和其他环境变量,go命令可以从代理下载zip文件,或者克隆源码管理存储库并从中创建zip文件。-json标志可以用来查找下载的 zip文件及其在模块缓存中提取的内容的位置。
golang.org/x/mod/zip包可以用来以编程方式创建、提取或检查压缩文件的内容。
File path and size constraints 文件路径和大小约束
对模块zip文件的内容有一些限制。这些限制确保zip文件可以在各种平台上安全和一致地被提取。
-
模块 zip文件最多可以有500 MiB的大小。
go.mod文件被限制在16 MB以内。LICENSE文件也被限制在16 MB以内。这些限制的存在是为了减轻对用户、代理和模块生态系统的其他部分的拒绝服务攻击。在模块目录树中包含超过500 MiB的文件的存储库应该在提交时标记模块版本,只包括构建模块包所需的文件;视频、模型和其他大型资产通常不需要构建。 -
模块zip文件中的每个文件必须以前缀
$module@$version/开始,其中$module是模块路径,$version是版本,例如golang.org/x/mod@v0.3.0/。模块路径必须是有效的,版本必须是有效的和经典的,并且版本必须与模块路径的主版本后缀匹配。具体定义和限制,请参见Module paths and versions(模块路径和版本)。 -
文件模式、时间戳和其他元数据被忽略。
-
空目录(路径以斜线结尾的条目)可能包含在模块zip文件中,但不会被提取。
go命令在它创建的压缩文件中不包括空目录。 -
符号链接和其他不规则的文件在创建zip文件时被忽略,因为它们在不同的操作系统和文件系统中是不可移植的,也没有可移植的方法在zip文件格式中表示它们。
-
在创建zip文件时,名为
vendor的目录内的文件被忽略,因为主模块外的vendor目录从不被使用。 -
在创建zip文件时,包含
go.mod文件的目录中的文件(模块根目录除外)将被忽略,因为它们不是模块的一部分。go命令在提取文件时忽略了包含go.mod文件的子目录。 -
在Unicode大小写折叠下,zip文件中的任何两个文件的路径都不可能相等(见strings.EqualFold)。这保证了在不区分大小写的文件系统中提取文件时不会出现冲突。
-
go.mod文件可能出现在顶层目录($module@$version/go.mod)中,也可能不出现。如果出现,它的名字必须是go.mod(全小写)。名为go.mod的文件不允许出现在任何其他目录中。 -
模块中的文件和目录名可以由Unicode字母、ASCII数字、ASCII空格字符(U+0020)和ASCII标点字符
!#$%&()+,-.=@[]^_{}~组成。注意,包的路径可能不包含所有这些字符。参见module.CheckFilePath和module.CheckImportPath的区别。 -
在Windows上,第一个点之前的文件或目录名不能是保留文件名,无论大小写(
CON、com1、NuL等)。
1.4.12 - 私有模块
Private modules 私有模块
Go模块经常是在版本控制服务器和模块代理上开发和发布的,这些模块在公共互联网上是不可用的。go 命令可以从私有资源中下载和构建模块,不过通常需要一些配置。
下面的环境变量可以用来配置对私有模块的访问。详情请参见Environment variables(环境变量)。有关控制发送到公共服务器的信息的信息,也请参见Privacy(隐私)。
GOPROXY—— 模块代理URL的列表。go命令将尝试按顺序从每个服务器下载模块。关键字direct指示go命令从其开发的版本控制存储库中下载模块,而不是使用代理。GOPRIVATE—— 应该被视为私有的模块路径前缀的 glob 模式列表。作为GONOPROXY和GONOSUMDB的默认值。GONOPROXY—— 不应从代理下载的模块路径前缀的 glob 模式列表。go命令将从开发模块的版本控制存储库中下载匹配的模块,而不考虑GOPROXY。GONOSUMDB—— 不应使用公共校验和数据库 sum.golang.org 进行检查的模块路径前缀的 glob 模式列表。GOINSECURE—— 可以通过HTTP和其他不安全协议检索的模块路径前缀的 glob 模式列表。
这些变量可以在开发环境中设置(例如,在 .profile 文件中),也可以用 go env -w 永久设置。
本节的其余部分描述了提供访问私有模块代理和版本控制存储库的常见模式。
Private proxy serving all modules 为所有模块提供服务的私有代理
为所有模块(公共和私有)提供服务的中央私有代理服务器为管理员提供了最大程度的控制,并且对单个开发人员来说需要的配置最少。
要配置go命令以使用这样的服务器,请设置以下环境变量,将https://proxy.corp.example.com替换为你的代理URL,将corp.example.com替换为你的模块前缀。
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=corp.example.com
GOPROXY 设置指示 go 命令仅从 https://proxy.corp.example.com 下载模块;go 命令不会连接到其他代理或版本控制存储库。
GONOSUMDB 设置指示 go 命令不使用公共校验和数据库来验证路径以 corp.example.com 开头的模块。
以这种配置运行的代理可能需要对私有版本控制服务器进行读取访问。它还需要访问公共互联网来下载公共模块的新版本。
有几种现有的GOPROXY服务器实现可以以这种方式使用。最小的实现将从module cache(模块缓存)目录中提供文件,并使用go mod download(带有适当的配置)来检索丢失的模块。
Private proxy serving private modules 为私有模块提供服务的私有代理
私人代理服务器可以为私人模块提供服务,而不需要为公开的模块提供服务。go命令可以被配置为在私人服务器上无法使用的模块时回退到公共源。
要配置go命令以这种方式工作,请设置以下环境变量,将https://proxy.corp.example.com替换为代理URL,将corp.example.com替换为模块前缀:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org,direct
GONOSUMDB=corp.example.com
GOPROXY 设置指示 go 命令首先尝试从 https://proxy.corp.example.com 下载模块。如果该服务器的回应是404 (Not Found)或410 (Gone),go命令将回退到https://proxy.golang.org,在之后才是直接连接到存储库。
GONOSUMDB 设置指示 go 命令不使用公共校验和数据库来验证路径以 corp.example.com 开头的模块。
请注意,在这种配置下使用的代理仍然可以控制对公共模块的访问,即使它不为公共模块提供服务。如果代理以404或410以外的错误状态响应请求,go命令将不会回退到GOPROXY列表的后面条目。例如,代理可能会对具有不合适许可证或具有已知安全漏洞的模块响应403 (Forbidden) 。
Direct access to private modules 直接访问私有模块
go命令可以被配置为绕过公共代理,并直接从版本控制服务器下载私有模块。当无法运行私有代理服务器时,这非常有用。
要配置 go 命令以这种方式工作,请设置 GOPRIVATE,将私有模块前缀替换为 corp.example.com :
GOPRIVATE=corp.example.com
在这种情况下,不需要更改GOPROXY变量。它的默认值是https://proxy.golang.org,direct,它指示go 命令首先尝试从https://proxy.golang.org,然后在代理响应404 (Not Found)或410 (Gone)时回退到直接连接。
GOPRIVATE设置指示go 命令不要连接到代理或以corp.example.com开头的模块的校验和数据库。
可能仍需要内部HTTP服务器来将模块路径解析为存储库URL。例如,当 go 命令下载模块 corp.example.com/mod 时,它将向 https://corp.example.com/mod?go-get=1发送一个 GET 请求,并在响应中查找存储库的 URL。要避免这种需求,请确保每个私有模块路径都有一个VCS后缀(如.git)来标记存储库根的前缀。例如,当 go 命令下载模块 corp.example.com/repo.git/mod 时,它将在 https://corp.example.com/repo.git 或 ssh://corp.example.com/repo.git中克隆 Git 存储库,而不需要发出额外的请求。
开发人员将需要对包含私有模块的存储库具有读取权限。这可以在全局VCS配置文件中配置,如.gitconfig。好将VCS工具配置为不需要交互式身份验证提示。默认情况下,在调用Git时,go 命令通过设置GIT_TERMINAL_PROMPT=0来禁用交互式提示,但它会遵守显式设置。
Passing credentials to private proxies 将凭据传递给私有代理
go 命令在与代理服务器通信时支持 HTTPbasic authentication(基本身份验证)。
凭证可以在.netrc 文件中指定。例如,包含以下几行的.netrc文件将配置go 命令用给定的用户名和密码连接到proxy.corp.example.com机器上。
machine proxy.corp.example.com
login jrgopher
password hunter2
文件的位置可以通过NETRC环境变量来设置。如果没有设置NETRC,go 命令将读取$HOME/.netrc(在类UNIX平台上),或读取%USERPROFILE%\_netrc(在Windows上)。
.netrc中的字段用空格、制表符和换行符分隔。遗憾的是,这些字符不能用于用户名或密码。还要注意的是,计算机名不能是一个完整的URL,因此不能为同一台机器上的不同路径指定不同的用户名和密码。
另外,凭证可以直接在GOPROXY的URL中指定。例如:
GOPROXY=https://jrgopher:hunter2@proxy.corp.example.com
采取这种方法时要小心:环境变量可能会出现在shell历史记录和日志中。
Passing credentials to private repositories 将凭证传递给私有存储库
go 命令可以直接从版本控制储存库中下载模块。如果没有使用私有代理,这对私有模块是必要的。参见Direct access to private modules(直接访问私有模块)的配置。
go 命令在直接下载模块时运行git等版本控制工具。这些工具执行它们自己的身份验证,所以你可能需要在工具特定的配置文件(如.gitconfig)中配置凭证。
为了确保这项工作顺利进行,请确保go 命令使用正确的存储库URL,并且版本控制工具不需要交互式输入密码。go 命令优先使用 https:// URL,而不是ssh://等其他方案,除非在查找存储库 URL 时指定了方案。特别是对于 GitHub 存储库,go 命令假定为 https://。
对于大多数服务器,你可以将客户端配置为通过HTTP进行身份验证。例如,GitHub 支持使用 OAuth 个人访问令牌作为 HTTP 密码。你可以将HTTP密码存储在.netrc文件中,就像将凭证传递给私有代理时一样。
另外,你也可以将https:// URL重写成另一种方案。例如,在.gitconfig中:
[url "git@github.com:"]
insteadOf = https://github.com/
更多信息,请参见为什么 “go get “在克隆存储库时使用HTTPS?
Privacy 隐私
go 命令可以从模块代理服务器和版本控制系统下载模块和元数据。环境变量GOPROXY控制使用哪些服务器。环境变量GOPRIVATE和GONOPROXY控制从代理服务器获取哪些模块。
GOPROXY的默认值是:
https://proxy.golang.org,direct
在此设置下,当go 命令下载模块或模块元数据时,它将首先向proxy.golang.org发送请求,这是一个由谷歌(privacy policy(隐私策略))运营的公共模块代理。有关在每个请求中发送哪些信息的详细信息,请参见GOPROXY 协议。go 命令不会传输个人身份信息,但它会传输所请求的完整模块路径。如果代理以404 (Not Found)或410 (Gone) 状态响应,go 命令将尝试直接连接到提供该模块的版本控制系统。详见Version control systems(版本控制系统)。
GOPRIVATE 或 GONOPROXY 环境变量可以被设置为与模块前缀匹配的 glob 模式列表,这些模块前缀是私有的,不应该从任何代理请求。例如:
GOPRIVATE=*.corp.example.com,*.research.example.com
GOPRIVATE只是作为GONOPROXY和GONOSUMDB的默认值,因此没有必要设置GONOPROXY,除非GONOSUMDB应该有一个不同的值。当模块路径与GONOPROXY匹配时,go 命令将忽略该模块的GOPROXY,并直接从其版本控制存储库中获取它。当没有代理为私有模块提供服务时,这很有用。参见Direct access to private modules(直接访问私有模块)。
如果有一个受信任的代理为所有模块提供服务,那么GONOPROXY就不应该被设置。例如,如果 GOPROXY 被设置为一个源,那么go 命令将不会从其他源下载模块。在这种情况下仍应设置GONOSUMDB。
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=*.corp.example.com,*.research.example.com
如果有一个受信任的代理仅为私有模块提供服务,那么不应该设置GONOPROXY,但必须注意确保该代理以正确的状态码进行响应。例如,请考虑以下配置:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org
GONOSUMDB=*.corp.example.com,*.research.example.com
假设由于输入错误,开发人员试图下载一个不存在的模块。
go mod download corp.example.com/secret-product/typo@latest
go 命令首先从proxy.corp.example.com请求此模块。如果该代理响应404 (Not Found)或410 (Gone),那么go 命令将回退到proxy.golang.org,在请求URL中传输secret-product路径。如果私人代理响应任何其他错误码,那么go 命令将打印错误,并且不会回退到其他源。
除了代理之外,go 命令还可以连接到校验和数据库,以验证go.sum中没有列出的模块的加密散列。GOSUMDB环境变量设置校验和数据库的名称、URL和公钥。GOSUMDB 的默认值是 sum.golang.org,它是由 Google (privacy policy(隐私策略))运营的公共校验和数据库。关于每次请求所传送的内容,请参见Checksum database(校验和数据库)。与代理一样,go 命令不会传输个人身份信息,但它会传输所请求的完整模块路径,而且校验和数据库无法计算非公共模块的校验和。
可以将GONOSUMDB环境变量设置为指示哪些模块是私有的并且不应从校验和数据库请求的模式。 GOPRIVATE作为GONOSUMDB和GONOPROXY的默认值,因此没有必要设置GONOSUMDB,除非GONOPROXY应该有不同的值。
代理可以mirror the checksum database(镜像校验和数据库)。如果GOPROXY中的代理执行此操作,go 命令将不会直接连接到校验和数据库。
GOSUMDB可以被设置为off,以完全禁止使用校验和数据库。使用此设置时,go 命令将不会对下载的模块进行身份验证,除非它们已经在go.sum中。请参阅Authenticating modules(验证模块)。
1.4.13 - 模块缓存
Module cache 模块缓存
模块缓存是go命令存储下载模块文件的目录。模块缓存与构建缓存不同,构建缓存包含已编译的包和其他构建构件。
模块缓存的默认位置是 $GOPATH/pkg/mod。要使用其他位置,请设置GOMODCACHEenvironment variable(环境变量)。
模块缓存没有最大大小,go命令不会自动删除其内容。
缓存可以由同一台机器上开发的多个 Go 项目共享。无论主模块的位置如何,go命令都会使用相同的缓存。go命令的多个实例可以同时安全地访问同一个模块缓存。
go命令在缓存中创建具有只读权限的模块源文件和目录,以防止模块下载后被意外更改。这有一个不幸的副作用,就是难以用rm -rf等命令删除缓存。取而代之的是,缓存可以用go clean -modcache来删除。另外,当使用-modcacherw标志时,go命令将创建具有读写权限的新目录。这增加了编辑、测试和其他程序修改模块缓存中文件的风险。go mod verify 命令可以用来检测对主模块的依赖项的修改。它扫描每个模块依赖项的提取内容,并确认它们与go.sum中预期的散列匹配。
下表解释了模块缓存中大多数文件的用途。省略了一些临时文件(锁定文件、临时目录)。对于每个路径,$module是一个模块路径,$version是一个版本。以斜线(/)结尾的路径是目录。模块路径和版本中的大写字母用感叹号转义(Azure被转义为!azure)以避免在不区分大小写的文件系统上发生冲突。
| Path | Description |
|---|---|
$module@$version/
包含模块.zip文件的提取内容的目录。它用作已下载模块的模块根目录。如果原始模块没有go.mod文件,那么它将不包含go.mod文件。
cache/download/
包含从模块代理下载的文件和从版本控制系统获得的文件的目录。这个目录的布局遵循GOPROXY 协议,因此当由HTTP文件服务器提供服务或用file://URL引用此目录时,此目录可以作为一个代理使用。
cache/download/$module/@v/list
已知版本的列表(见GOPROXY 协议)。这可能会随着时间的推移而改变,因此go命令通常会获取新的副本,而不是重新使用这个文件。
cache/download/$module/@v/$version.info
有关版本的JSON元数据。(见GOPROXY 协议)。这可能会随着时间的推移而改变,因此go命令通常会获取新的副本,而不是重复使用这个文件。
cache/download/$module/@v/$version.mod
这个版本的go.mod文件(见GOPROXY 协议)。如果原来的模块没有go.mod文件,则这就是一个没有需求的合成文件。
cache/download/$module/@v/$version.zip
模块的压缩内容(见GOPROXY 协议和模块压缩文件)。
cache/download/$module/@v/$version.ziphash
.zip文件中的文件的加密哈希值。请注意.zip文件本身没有被哈希化,因此文件的顺序、压缩、对齐和元数据不会影响哈希值。当使用一个模块时,go命令会验证这个哈希值是否与go.sum中的对应行匹配。go mod verify命令检查模块.zip文件和提取的目录的哈希值是否与这些文件相符。
cache/download/sumdb/
包含从checksum database(校验和数据库)(通常是sum.golang.org)下载的文件的目录。
cache/vcs/
包含直接从源获取的模块的克隆的版本控制存储库。目录名称是由存储库类型和 URL 衍生出来的十六进制编码的哈希值。存储库在磁盘上的大小是经过优化的。例如,克隆的Git存储库在可能的情况下是裸露和浅层的。
1.4.14 - 验证模块
Authenticating modules 验证模块
当go命令下载模块zip 文件或go.mod文件到module cache(模块缓存)时,它会计算加密散列并将其与已知值进行比较,以验证该文件自首次下载以来没有更改。如果下载的文件没有正确的散列值,go命令会报告安全错误。
对于go.mod文件,go命令从文件内容中计算出散列值。对于模块zip文件,go命令以确定的顺序从归档文件中的文件名称和内容计算散列值。散列值不受文件顺序、压缩、对齐和其他元数据的影响。有关散列值的实现细节,请参见 golang.org/x/mod/sumdb/dirhash。
go命令将每个散列值与主模块的go.sum文件中的对应行进行比较。如果散列值与go.sum中的散列值不同,go命令将报告安全错误,并删除下载的文件而不将其加入模块缓存。
如果go.sum文件不存在,或者它不包含下载文件的散列值,则go命令可以使用校验和数据库(公共可用模块的全局散列源)验证散列值。散列值被验证之后,go命令会将其加入go.sum,并将下载的文件加入模块缓存中。如果模块是私有的(被GOPRIVATE或GONOSUMDB环境变量匹配),或者如果校验和数据库被禁用(通过设置GOSUMDB=off),则go命令接受散列值并将文件添加到模块缓存中,而不进行验证。
模块缓存通常由系统中的所有Go项目共享,每个模块可能有自己的go.sum文件,其散列值可能不同。为了避免信任其他模块,go命令在访问模块缓存中的文件时,使用主模块的go.sum来验证散列值。zip文件的散列值计算成本很高,所以go命令检查与zip文件一起存储的预先计算的散列值,而不是重新散列文件。go mod verify命令可以用来检查zip文件和提取的目录自从被添加到模块缓存后是否被修改过。
go.sum files
模块的根目录中可能有一个名为go.sum的文本文件,以及跟随它的go.mod文件。go.sum文件包含模块的直接和间接依赖的加密散列值。当go命令将模块.mod或.zip文件下载到module cache(模块缓存)中时,它会计算散列并检查该散列是否与主模块的go.sum文件中的相应散列匹配。如果模块没有依赖项,或者如果使用replace 指令将所有依赖项替换为本地目录,那么go.sum可能为空或不存在。
go.sum中的每一行都有三个用空格隔开的字段:模块路径,版本(可能以/go.mod结尾),以及散列值。
-
模块路径是散列值所属模块的名称。
-
版本是散列值所属的模块的版本。如果版本以
/go.mod结尾,则散列值仅适用于该模块的go.mod文件;否则,散列值适用于该模块的.zip文件中的文件。 -
散列值由算法名称(如
h1)和一个base64编码的加密散列组成,用冒号(:)分开。目前,SHA-256(h1)是唯一支持的散列算法。如果将来发现了SHA-256的漏洞,将增加对另一种算法(命名为h2,以此类推)的支持。
go.sum文件可能包含一个模块的多个版本的散列值。go命令可能需要从依赖项的多个版本加载go.mod文件,以进行最小的版本选择。go.sum也可能包含不再需要的模块版本的散列值(例如,在升级之后)。go mod tidy将添加缺失的散列值,并从go.sum中删除不必要的散列值。
Checksum database 校验和数据库
校验和数据库是go.sum行的全局源。go命令可以在许多情况下使用它来检测代理或源服务器的错误行为。
校验和数据库允许所有公开可用的模块版本的全局一致性和可靠性。它使不被信任的代理成为可能,因为它们无法在不被发现的情况下提供错误的代码。它还确保与特定版本相关的bit位不会从一天到另一天发生变化,即使模块的作者后来更改了其存储库中的标签。
校验和数据库由Google运营的sum.golang.org提供服务。它是由Trillian支持的go.sum行散列的透明日志(或“Merkle 树”)。 Merkle 树的主要优点是,独立的审计人员可以验证它没有被篡改,因此它比简单的数据库更值得信赖。
go命令使用最初在Proposal: Secure the Public Go Module Ecosystem中概述的协议与校验和数据库进行交互。
下表列出了校验和数据库必须响应的查询。对于每个路径,$base是校验和数据库URL的路径部分,$module是模块路径,而$version是版本。例如,如果校验和数据库的URL是https://sum.golang.org,而客户端请求的是golang.org/x/text模块的记录,版本为v0.3.2,那么客户端将发送https://sum.golang.org/lookup/golang.org/x/text@v0.3.2的GET请求。
为了避免在从不区分大小写的文件系统中提供服务时出现歧义,$module和$version元素被进行了case-encoded(大小写编码),将每个大写字母替换为感叹号,后跟相应的小写字母。这允许模块example.com/M和example.com/m同时被存储在磁盘上,因为前者被编码为example.com/!m。
路径中由方括号包围的部分,如[.p/$W]表示可选的值。
| Path | Description |
|---|---|
$base/latest
返回最新日志的有符号编码的树描述。这个签名的描述是以note(注释)的形式出现的,它是由一个或多个服务器密钥签名的文本,可以用服务器的公钥进行验证。树描述提供了树的大小和该大小的树头的散列值。这中编码在golang.org/x/mod/sumdb/tlog#FormatTree中有描述。
$base/lookup/$module@$version
返回$version中关于$module的条目的日志记录编号,后跟记录的数据(即$version中的$module的go.sum行)和包含该记录的有符号编码的树描述。
$base/tile/$H/$L/$K[.p/$W]
返回一个log tile,它是组成日志的一部分的一组散列。每个tile定义在tile级别$L,左起$K的二维坐标中,tile高度为$H。可选的.p/$W后缀表示只有$W散列的部分日志块。如果没有找到部分tile,客户必须回退到获取完整的tile。
$base/tile/$H/data/$K[.p/$W]
返回/tile/$H/0/$K[.p/$W]中的叶子散列的记录数据(带有字面data路径元素)。
如果go命令查询校验和数据库,那么第一步就是通过/lookup端点检索记录数据。如果日志中尚未记录模块版本,校验和数据库将尝试在回复前从原服务器上获取它。这个/lookup数据提供了这个模块版本的sum(和)以及它在日志中的位置,这就通知了客户端应该取哪些tile来执行证明。在向主模块的go.sum文件添加新的go.sum行之前,go命令执行 “inclusion(包含性)“证明(即日志中存在特定记录)和 “consistency(一致性)“证明(即树没有被篡改)。重要的是,如果没有首先根据签名的树散列值对其进行身份认证,以及根据客户的签名树散列值时间线对签名树散列值进行认证,就不应该使用来自/lookup的数据。
已签名的树状散列值和由校验数据库提供的新瓦片都存储在模块缓存中,所以go命令只需要获取缺少的瓦片。
go命令不需要直接连接到校验和数据库。它可以通过镜像mirrors the checksum database(校验和数据库)并支持上述协议的模块代理来请求模块和。这对于阻止组织外部请求的私有企业代理特别有帮助。
GOSUMDB环境变量标识要使用的校验和数据库的名称,还可以选择其公钥和URL,如:
GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
go命令知道sum.golang.org的公钥,也知道sum.golang.google.cn这个名字(在中国大陆可用)连接到sum.golang.org的校验和数据库;使用其他数据库需要显式给出公钥。URL默认为https://,后跟数据库名称。
GOSUMDB默认为sum.golang.org,这是由Google运营的Go校验和数据库。有关该服务的隐私政策,请参见 https://sum.golang.org/privacy。
如果 GOSUMDB 被设置为off,或者在调用 go get 时使用了 -insecure 标志,则不会查询校验和数据库,并接受所有未识别的模块,代价是放弃了对所有模块的可重复下载的安全保证。一个更好的方法是使用GOPRIVATE或GONOSUMDB环境变量来绕过特定模块的校验和数据库。详见Private Modules(私有模块)。
go env -w命令可用于为将来的go命令调用设置这些变量。
1.4.15 - 环境变量
Environment variables 环境变量
go命令中的模块行为可以使用下面列出的环境变量进行配置。这个列表只包括与模块相关的环境变量。有关go命令识别的所有环境变量的列表,请参阅go help environment。
GO111MODULE
控制go命令是在模块感知模式还是GOPATH模式下运行。有三个值可以识别:
-
off:go命令忽略go.mod文件,并在GOPATH模式下运行。 -
on(或unset):go命令在模块感知模式下运行,即使不存在go.mod文件。 -
auto:如果当前目录或任何父目录中存在go.mod文件,go命令将以模块感知模式运行。在Go 1.15及以下版本中,这是默认的。
更多信息请参见模块感知命令。
GOMODCACHE
go命令将存储下载的模块和相关文件的目录。关于此目录结构的详细信息,请参见模块缓存。如果未设置GOMODCACHE,它默认为$GOPATH/pkg/mod。
GOINSECURE
以逗号分隔的模块路径前缀 glob 模式列表(采用 Go的 path.Match 的语法),可能总是以不安全的方式获取。仅适用于被直接获取的依赖项。与go get上的-insecure标志不同,GOINSECURE不会禁用模块校验和数据库验证(module checksum database validation)。可以用GOPRIVATE或GONOSUMDB来实现这一点。
GONOPROXY
以逗号分隔的模块路径前缀 glob 模式列表(采用Go的path.Match语法),应该总是直接从版本控制存储库获取,而不是从模块代理获取。如果没有设置GONOPROXY,它默认为GOPRIVATE。参见Privacy(隐私)。
GONOSUMDB
以逗号分隔的模块路径前缀 glob 模式列表(采用Go的path.Match语法),go 不应使用校验数据库来验证校验。如果未设置 GONOSUMDB,它默认为 GOPRIVATE。参见Privacy(隐私)。
GOPATH
在 GOPATH 模式中,GOPATH 变量是一个可能包含 Go 代码的目录列表。在模块感知模式下,module cache(模块缓存)存储在第一个 GOPATH 目录的 pkg/mod 子目录中。缓存之外的模块源代码可以存储在任何目录中。如果未设置GOPATH,它默认为用户的主目录(home directory)的go子目录。
GOPRIVATE
以逗号分隔的模块路径前缀的 glob 模式列表(采用Go的path.Match语法),应被视认为是私有的。GOPRIVATE是GONOPROXY和GONOSUMDB的默认值。参见Privacy(隐私)。GOPRIVATE 也决定了一个模块是否被视为 GOVCS 的私有模块。
GOPROXY
模块代理URL的列表,用逗号(,)或管道符 |分隔。当go命令查询有关模块的信息时,它会依次联系列表中的每个代理,直到收到成功的响应或终端错误。代理可能会响应404(Not Found)或410(Gone)状态,表示该模块在该服务器上不可用。
go命令的错误回退行为(error fallback behavior)是由URL之间的分隔符决定的。如果代理URL后面是逗号,go命令在404或410错误后会回退到下一个URL;所有其他错误都被视为终端错误。如果代理URL后面跟着管道,则go命令在出现任何错误(包括超时等非HTTP错误)后回退到下一个源。GOPROXY URLs可以有https、http或file等协议。如果一个URL没有协议,则假定为https。模块缓存可以直接作为文件代理使用:
GOPROXY=file://$(go env GOMODCACHE)/cache/download
有两个关键词可以用来代替代理URL:
-
off:不允许从任何源下载模块。 -
direct: 直接从版本控制存储库下载,而不是使用模块代理。
GOPROXY默认为https://proxy.golang.org,direct。在该配置下,go命令首先联系Google运行的Go模块镜像,如果该镜像没有模块,则回退到直接连接。请参见https://proxy.golang.org/privacy了解镜像的隐私政策。可以设置 GOPRIVATE 和 GONOPROXY 环境变量,以防止使用代理下载特定模块。关于隐私代理配置的信息,请参见Privacy(隐私)。
有关如何使用代理的更多信息,请参见Module proxies(模块代理)和Resolving a package to a module(将包解析为模块)。
GOSUMDB
标识要使用的校验和数据库的名称以及可选的公钥和 URL。例如:
GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
go命令知道sum.golang.org的公钥,也知道名称为sum.golang.google.cn(在中国大陆可用)连接到sum.golang.org数据库;使用任何其他数据库都需要显式地给出公钥。URL默认为https://后跟数据库名。
GOSUMDB默认为sum.golang.org,由Google运行的Go校验和数据库(checksum database)。有关该服务的隐私政策,请参见 https://sum.golang.org/privacy。
如果 GOSUMDB 被设置为off,或者在调用 go get 时使用了 -insecure 标志,则不会查询校验和数据库,所有未识别的模块都会被接受,代价是放弃对所有模块进行验证的可重复下载的安全保证。绕过特定模块的校验和数据库的更好方法是使用GOPRIVATE或GONOSUMDB环境变量。
更多信息请参见Authenticating modules(验证模块)和Privacy(隐私)。
GOVCS
控制go命令在下载公共和私有模块(由其路径是否匹配GOPRIVATE中的模式来定义)或其他与glob模式相匹配的模块时可以使用的版本控制工具集。如果没有设置GOVCS,或者某个模块不符合GOVCS中的任何模式,go命令可以对公共模块使用git和hg,对私有模块使用任何已知的版本控制工具。具体来说,go命令的行为就像GOVCS被设置为public:git|hg,private:all,完整的解释请参见 用GOVCS控制版本控制工具。
GOWORK
GOWORK环境变量指示go命令使用提供的go.work文件进入工作区模式。如果GOWORK被设置为off,工作区模式将被禁用。这可以用来在单模块模式下运行go命令:例如,GOWORK=off go build .在单模块模式下构建.包。如果GOWORK为空,go命令将搜索go.work文件,如工作区部分所述。
1.4.16 - 词汇表
Glossary词汇表
build constraint
A condition that determines whether a Go source file is used when compiling a package. Build constraints may be expressed with file name suffixes (for example, foo_linux_amd64.go) or with build constraint comments (for example, // +build linux,amd64). See Build Constraints.
build constraint (构建约束):决定在编译包时是否使用Go源文件的条件。构建约束可以用文件名后缀来表示(例如,foo_linux_amd64.go),也可以用构建约束的注释来表达(例如,// +build linux,amd64)。参见构建约束。
build list
The list of module versions that will be used for a build command such as go build, go list, or go test. The build list is determined from the main module’s go.mod file and go.mod files in transitively required modules using minimal version selection. The build list contains versions for all modules in the module graph, not just those relevant to a specific command.
build list: 将用于构建命令的模块版本列表,如go build、go list或go test。构建列表是由主模块的go.mod文件和中转所需模块的go.mod文件决定的,使用最小版本选择。构建列表包含了模块图中所有模块的版本,而不仅仅是与特定命令相关的模块。
canonical version
A correctly formatted version without a build metadata suffix other than +incompatible. For example, v1.2.3 is a canonical version, but v1.2.3+meta is not.
典型版本。一个格式正确的版本,除了+incompatible之外,没有构建元数据的后缀。例如,v1.2.3是一个典型的版本,但v1.2.3+meta不是。
current module
Synonym for main module.
当前模块。主模块的同义词。
deprecated module
A module that is no longer supported by its authors (though major versions are considered distinct modules for this purpose). A deprecated module is marked with a deprecation comment in the latest version of its go.mod file.
deprecated module(废弃的模块)。一个不再被其作者支持的模块(尽管主要版本在此被视为独立的模块)。被废弃的模块在其go.mod文件的最新版本中被标记为废弃注释。
direct dependency
A package whose path appears in an import declaration in a .go source file for a package or test in the main module, or the module containing such a package. (Compare indirect dependency.)
直接依赖关系。一个软件包,其路径出现在主模块中的包或测试的.go源文件的导入声明中,或者包含这样一个包的模块。(比较间接依赖)。
direct mode
A setting of environment variables that causes the go command to download a module directly from a version control system, as opposed to a module proxy. GOPROXY=direct does this for all modules. GOPRIVATE and GONOPROXY do this for modules matching a list of patterns.
直接模式。一种环境变量的设置,使go命令直接从版本控制系统中下载模块,而不是通过模块代理。GOPROXY=direct 对所有模块都是如此。GOPRIVATE和GONOPROXY对符合模式列表的模块做此处理。
go.mod file
The file that defines a module’s path, requirements, and other metadata. Appears in the module’s root directory. See the section on go.mod files.
go.mod 文件。定义一个模块的路径、要求和其他元数据的文件。出现在模块的根目录下。参见 go.mod 文件一节。
go.work file
The file that defines the set of modules to be used in a workspace. See the section on go.work files
go.work文件:定义工作区中使用的模块集的文件。见go.work文件一节
import path
A string used to import a package in a Go source file. Synonymous with package path.
import路径。用来在 Go 源文件中导入软件包的字符串。与软件包路径同义。
indirect dependency
A package transitively imported by a package or test in the main module, but whose path does not appear in any import declaration in the main module; or a module that appears in the module graph but does not provide any package directly imported by the main module. (Compare direct dependency.)
间接依赖。一个被主模块中的包或测试间接导入的包,但其路径没有出现在主模块的任何导入声明中;或者一个出现在模块图中的模块,但没有提供任何被主模块直接导入的包。(比较直接依赖)。
lazy module loading
A change in Go 1.17 that avoids loading the module graph for commands that do not need it in modules that specify go 1.17 or higher. See Lazy module loading.
懒惰的模块加载。Go 1.17中的一个变化,在指定go 1.17或更高版本的模块中避免为不需要的命令加载模块图。参见 “懒惰模块加载”。
main module
The module in which the go command is invoked. The main module is defined by a go.mod file in the current directory or a parent directory. See Modules, packages, and versions.
主模块。调用go命令的模块。主模块由当前目录或父目录中的go.mod文件定义。参见模块、包和版本。
major version
The first number in a semantic version (1 in v1.2.3). In a release with incompatible changes, the major version must be incremented, and the minor and patch versions must be set to 0. Semantic versions with major version 0 are considered unstable.
主版本。语义版本中的第一个数字(1在v1.2.3中)。在有不兼容变化的版本中,主版本必须被递增,而次版本和补丁版本必须被设置为0。 主版本为0的语义版本被认为是不稳定的。
major version subdirectory
A subdirectory within a version control repository matching a module’s major version suffix where a module may be defined. For example, the module example.com/mod/v2 in the repository with root path example.com/mod may be defined in the repository root directory or the major version subdirectory v2. See Module directories within a repository.
major version subdirectory(主要版本子目录)。版本控制库中的一个子目录,与模块的主要版本后缀相匹配,在这里可以定义一个模块。例如,根路径为 example.com/mod 的版本库中的模块 example.com/mod/v2 可以定义在版本库根目录或主要版本子目录 v2 中。参见版本库内的模块目录。
major version suffix
A module path suffix that matches the major version number. For example, /v2 in example.com/mod/v2. Major version suffixes are required at v2.0.0 and later and are not allowed at earlier versions. See the section on Major version suffixes.
主要版本的后缀。一个与主要版本号相匹配的模块路径后缀。例如,/v2 在 example.com/mod/v2。主要版本后缀在v2.0.0及以后的版本中是必须的,在早期版本中不允许使用。参见主要版本后缀一节。
minimal version selection (MVS)
The algorithm used to determine the versions of all modules that will be used in a build. See the section on Minimal version selection for details.
最小版本选择(MVS)。用来确定构建中使用的所有模块的版本的算法。详见最小版本选择一节。
minor version
The second number in a semantic version (2 in v1.2.3). In a release with new, backwards compatible functionality, the minor version must be incremented, and the patch version must be set to 0.
次要版本。语义版本中的第二个数字(V1.2.3中为2)。在具有新的、向后兼容的功能的版本中,次要版本必须被递增,而补丁版本必须被设置为0。
module
A collection of packages that are released, versioned, and distributed together.
模块。一组包的集合,它们被一起发布、版本化和分发。
module cache: A local directory storing downloaded modules, located in GOPATH/pkg/mod. See Module cache.
模块缓存。一个存储下载模块的本地目录,位于GOPATH/pkg/mod。参见模块缓存。
module graph
The directed graph of module requirements, rooted at the main module. Each vertex in the graph is a module; each edge is a version from a require statement in a go.mod file (subject to replace and exclude statements in the main module’s go.mod file).
模块图。模块需求的有向图,以主模块为根。图中的每个顶点都是一个模块;每条边都是来自 go.mod 文件中 require 语句的版本(受主模块的 go.mod 文件中的替换和排除语句制约)。
module graph pruning
A change in Go 1.17 that reduces the size of the module graph by omitting transitive dependencies of modules that specify go 1.17 or higher. See Module graph pruning.
模块图的修剪。Go 1.17中的一个变化,通过省略指定go 1.17或更高版本的模块的相互依赖关系来减少模块图的大小。参见模块图修剪。
module path
A path that identifies a module and acts as a prefix for package import paths within the module. For example, "golang.org/x/net".
模块路径。一个标识模块的路径,作为模块内包导入路径的前缀。例如,“golang.org/x/net”。
module proxy
A web server that implements the GOPROXY protocol. The go command downloads version information, go.mod files, and module zip files from module proxies.
模块代理。一个实现GOPROXY协议的网络服务器。go命令从模块代理处下载版本信息、go.mod文件和模块压缩文件。
module root directory
The directory that contains the go.mod file that defines a module.
模块根目录。包含定义模块的go.mod文件的目录。
module subdirectory
The portion of a module path after the repository root path that indicates the subdirectory where the module is defined. When non-empty, the module subdirectory is also a prefix for semantic version tags. The module subdirectory does not include the major version suffix, if there is one, even if the module is in a major version subdirectory. See Module paths.
模块子目录。模块路径在版本库根路径之后的部分,表示定义该模块的子目录。非空时,模块子目录也是语义版本标签的前缀。模块子目录不包括主要版本后缀(如果有的话),即使该模块位于主要版本子目录中。参见模块路径。
package
A collection of source files in the same directory that are compiled together. See the Packages section in the Go Language Specification.
包。在同一目录下的源文件的集合,这些文件被编译在一起。参见 Go 语言规范中的包部分。
package path
The path that uniquely identifies a package. A package path is a module path joined with a subdirectory within the module. For example "golang.org/x/net/html" is the package path for the package in the module "golang.org/x/net" in the "html" subdirectory. Synonym of import path.
包路径。唯一标识一个包的路径。包的路径是一个模块的路径与模块内的子目录相连接。例如 “golang.org/x/net/html “是模块 “golang.org/x/net “中 “html “子目录下的包的路径。进口路径的同义词。
patch version
The third number in a semantic version (3 in v1.2.3). In a release with no changes to the module’s public interface, the patch version must be incremented.
补丁版本。语义版本中的第三个数字(v1.2.3中为3)。在模块的公共接口没有变化的版本中,补丁版本必须被递增。
pre-release version
A version with a dash followed by a series of dot-separated identifiers immediately following the patch version, for example, v1.2.3-beta4. Pre-release versions are considered unstable and are not assumed to be compatible with other versions. A pre-release version sorts before the corresponding release version: v1.2.3-pre comes before v1.2.3. See also release version.
pre-release version(预发布版本)。在补丁版本后面紧跟着一系列点分隔的标识符,带有破折号的版本,例如,v1.2.3-beta4。预发布版本被认为是不稳定的,不被认为与其他版本兼容。预发布版本会在相应的发布版本之前排序:v1.2.3-pre会在v1.2.3之前。另见发布版本。
pseudo-version
A version that encodes a revision identifier (such as a Git commit hash) and a timestamp from a version control system. For example, v0.0.0-20191109021931-daa7c04131f5. Used for compatibility with non-module repositories and in other situations when a tagged version is not available.
pseudo-version(伪版本)。一个编码了修订标识符(如Git提交哈希值)和版本控制系统的时间戳的版本。例如,v0.0.0-20191109021931-daa7c04131f5。 用于与非模块仓库的兼容性,以及其他无法获得标记版本的情况。
release version
A version without a pre-release suffix. For example, v1.2.3, not v1.2.3-pre. See also pre-release version.
发布版本。一个没有预发布后缀的版本。例如,v1.2.3,而不是v1.2.3-pre。另见预发布版本。
repository root path
The portion of a module path that corresponds to a version control repository’s root directory. See Module paths.
仓库根路径。模块路径中与版本控制库的根目录相对应的部分。参见模块路径。
retracted version
A version that should not be depended upon, either because it was published prematurely or because a severe problem was discovered after it was published. See retract directive.
撤回的版本。一个不应该被依赖的版本,因为它被过早地发布,或者在发布后发现了严重的问题。参见retract指令。
semantic version tag
A tag in a version control repository that maps a version to a specific revision. See Mapping versions to commits.
语义版本标签。版本控制库中的一个标签,将一个版本映射到一个特定的修订版。参见版本与提交的映射。
selected version
The version of a given module chosen by minimal version selection. The selected version is the highest version for the module’s path found in the module graph.
选定的版本。通过最小版本选择选择的特定模块的版本。选择的版本是在模块图中发现的该模块路径的最高版本。
vendor directory
A directory named vendor that contains packages from other modules needed to build packages in the main module. Maintained with go mod vendor. See Vendoring.
vendor目录。一个名为vendor的目录,包含了其他模块的包,需要在主模块中构建包。用go mod vendor维护。参看vendoring。
version
An identifier for an immutable snapshot of a module, written as the letter v followed by a semantic version. See the section on Versions.
版本。一个模块的不可改变的快照的标识符,写成字母v,后面是语义版本。参见 “版本 “一节。
workspace
A collection of modules on disk that are used as the main modules when running minimal version selection (MVS). See the section on Workspaces
workspace(工作区)。磁盘上的模块集合,在运行最小版本选择(MVS)时被用作主要模块。见关于工作区的章节
1.5 - go.mod 文件参考
go.mod file reference - go.mod文件参考
每个 Go 模块都由一个 go.mod 文件定义,该文件描述了该模块的属性,包括它对其他模块和 Go 版本的依赖性。
这些属性包括:
- 当前模块的
模块路径。这应该是Go工具可以下载该模块的位置,例如模块代码的存储库位置。当与模块的版本号结合时,它可以作为唯一的标识符。它也是该模块中所有包的包路径的前缀。关于Go如何定位模块的更多信息,请参阅Go模块参考。 - 当前模块所需的
Go的最小版本。 - 当前模块所需的其他模块的最低版本列表。
- 指令,可选择用其他模块版本或本地目录
替换 (replace)所需模块,或排除 (exclude)所需模块的特定版本。
当你运行go mod init命令时,Go会生成一个go.mod文件。下面的例子创建了一个go.mod文件,将模块的模块路径设置为example/mymodule。
$ go mod init example/mymodule
使用go命令来管理依赖关系。这些命令确保你的go.mod文件中描述的需求保持一致,并且go.mod文件的内容是有效的。这些命令包括go get和go mod tidy以及go mod edit命令。
关于go命令的参考,请看go 命令。你可以通过输入go help command-name从命令行获得帮助,如go help mod tidy。
参见:
Example 示例
一个go.mod文件包括以下例子中的指令。这些在本主题的其他部分有描述。
module example.com/mymodule
go 1.14
require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)
replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
module 模块
声明模块的模块路径,它是模块的唯一标识符(与模块的版本号结合)。模块路径成为该模块包含的所有包的导入前缀。
更多信息请参见 Go Modules Reference 中的 module 指令。
Syntax 语法
module module-path
-
module-path
模块的模块路径,通常是 Go 工具可以下载该模块的存储库位置。对于版本
v2及以后的模块,该值必须以主版本号结尾,如/v2。
Examples 示例
下面的例子用example.com代替可以下载该模块的存储库域。
-
v0或v1模块的模块声明:module example.com/mymodule -
v2模块的模块路径:module example.com/mymodule/v2
Notes 注意事项
模块路径必须唯一标识你的模块。对于大多数模块,路径是一个URL,go命令可以在其中找到代码(或重定向到代码)。对于那些不会被直接下载的模块,模块路径可以是一些你能控制的名字,以确保唯一性。前缀example/也被保留下来,用于像这样的例子中。
更多细节,请参见管理依赖关系。
在实践中,模块路径通常是模块源的版本库域和版本库中的模块代码的路径。go命令在下载模块版本时依赖这种形式,来代表模块用户解决依赖关系。
即使你一开始不打算让你的模块供其他代码使用,使用它的存储库路径也是一种最佳做法,可以帮助你避免在以后发布模块时不得不重命名它。
如果一开始你不知道模块的最终存储库位置,可以考虑暂时使用一个安全的替代品,比如你拥有的域名或你控制的名称(如你的公司名称),以及模块名称或源目录的后续路径。更多信息,请参见管理依赖关系。
例如,如果你在stringtools目录下开发,你的临时模块路径可能是<company-name>/stringtools,如下面的例子,其中company-name是你公司的名字:
go mod init <company-name>/stringtools
go
表示该模块是按照指令指定的Go版本的语义来编写的。
更多信息请参见 Go 模块参考中的 go 指令。
Syntax 语法
go minimum-go-version
-
minimum-go-version
编译本模块中的包所需的最小Go版本。
Examples 示例
-
模块必须在1.14或更高版本的Go上运行:
go 1.14
Notes 注意事项
go指令最初是为了支持Go语言的向后不兼容的变化(见Go 2 过渡)。自从引入模块以来,没有任何不兼容的语言变化,但go指令仍会影响新的语言特性的使用:
- 对于模块内的包,编译器会拒绝使用
go指令指定的版本之后引入的语言特性。例如,如果一个模块的指令是go 1.12,它的包就不能使用1_000_000这样的数字字面量,这是在Go 1.13(版本)引入的。 - 如果一个较早的Go版本构建了该模块的一个包并遇到了编译错误,那么错误就会指出该模块是为一个较新的Go版本编写的。例如,假设一个模块是
go 1.13,其中一个包使用数字字面量1_000_000。如果该包是用Go 1.12 (版本)构建的,编译器就会注意到该代码是为Go 1.13(版本)编写的。
此外,go命令会根据go指令所指定的版本改变其行为。这有以下影响:
(1)在go 1.14或更高版本中,可以启用自动vendoring 。如果文件vendor/modules.txt存在并且与go.mod一致,就不需要显式使用-mod=vendor标志。
(2)在 go 1.16 或更高版本中,all包模式只匹配由主模块(main module)中的包和测试导入的包。这也是go mod vendor自引入模块以来所保留的包的集合。在较低的版本中,all也包括由主模块中的包导入的包的测试、对这些包的测试等等。
(3)在go 1.17或更高版本
-
go.mod文件包括一个明确的require指令,为每个模块提供由主模块中的包或测试过渡导入的任何包。(在 go 1.16 或更低版本中,只有在最小版本选择会选择不同版本的情况下,才会包括间接依赖。) 这个额外的信息使得模块图的修剪和延迟模块加载成为可能。 -
由于
// indirect依赖关系可能比以前的go版本多得多,间接依赖关系被记录在go.mod文件中的一个独立块中。 -
go mod vendor省略了go.mod和go.sum文件中的供应商依赖关系。(这允许在vendor的子目录中调用go命令来识别正确的主模块)。 -
go mod vendor在vendor/modules.txt中记录每个依赖关系的go.mod文件的go版本。
一个go.mod文件最多可以包含一个go指令。如果没有go指令,大多数命令会添加一个当前Go版本的go指令。
require
将模块声明为当前模块的依赖项,并指定所需模块的最小版本。
更多信息请参见 Go 模块参考中的 require 指令。
Syntax 语法
require module-path module-version
-
module-path
模块的模块路径,通常是模块源的存储库域和模块名称的连接。对于版本v2及以后的模块,该值必须以主要版本号结尾,如
/v2。 -
module-version
模块的版本。这可以是一个发布的版本号,如v1.2.3,或Go生成的伪版本号,如v0.0.0-20200921210052-fa0125251cc4。
Examples 示例
-
要求发布版本v1.2.3:
require example.com/othermodule v1.2.3 -
通过使用 Go 工具生成的伪版本号来要求其存储库中尚未标记的版本。
require example.com/othermodule v0.0.0-20200921210052-fa0125251cc4
Notes 注意事项
当你运行 go 命令时,例如 go get,Go 会为包含导入包的每个模块插入 require 指令。当一个模块还没有在其存储库中被标记时,Go 会分配一个它在运行命令时生成的伪版本号。
你可以通过使用replace指令让 Go 从其存储库以外的地方要求一个模块。
更多关于版本号的信息,请参见模块版本号。
关于管理依赖关系的更多信息,请参见下文:
replace 替换
将特定版本(或所有版本)的模块内容替换为另一个模块版本或本地目录。Go工具在解析依赖项时将使用替换路径。
更多信息请参见 Go 模块参考中的 replace 指令。
Syntax 语法
replace module-path [module-version] => replacement-path [replacement-version]
-
module-path要替换的模块的模块路径。
-
module-version可选的。要替换的特定版本。如果这个版本号被省略,该模块的所有版本都会被替换成箭头右侧的内容。
-
replacement-pathGo应该寻找所需模块的路径。这可以是一个模块路径,也可以是文件系统中与替换模块相关的目录的路径。如果这是一个模块路径,则必须指定一个替换版本(
replacement-version)的值。如果这是一个本地路径,则不能使用替换版本(replacement-version)的值。 -
replacement-version替换模块的版本。只有当
replacement-path是一个模块路径(不是本地目录)时,才可以指定替换版本。
Examples 示例
-
用模块存储库的一个分叉来替换
在下面的例子中,example.com/othermodule的任何版本都被替换成指定的分叉代码
require example.com/othermodule v1.2.3 replace example.com/othermodule => example.com/myfork/othermodule v1.2.3-fixed 当另一个模块路径替换一个模块时,不用更改要替换的模块中包的导入语句。
关于使用分叉的模块代码副本的更多信息,请参阅Requiring external module code from your own repository fork(从你自己的存储库分叉中请求外部模块代码)。
-
用不同的版本号替换
下面的例子指定使用
v1.2.3版本,而不是该模块的任何其他版本。require example.com/othermodule v1.2.2 replace example.com/othermodule => example.com/othermodule v1.2.3下面的例子用同一模块的
v1.2.3版本替换了模块v1.2.5版本。replace example.com/othermodule v1.2.5 => example.com/othermodule v1.2.3 -
用本地代码替换
下面的示例指定应使用本地目录替换模块的所有版本。
require example.com/othermodule v1.2.3 replace example.com/othermodule => ../othermodule下面的示例指定只能使用本地目录替换
v1.2.5。require example.com/othermodule v1.2.5 replace example.com/othermodule v1.2.5 => ../othermodule 关于使用模块代码的本地副本的更多信息,请参见Requiring module code in a local directory。
Notes 注意事项
当你想让Go使用另一个路径来查找模块的源代码时,可以使用replace指令来暂时用另一个值来替换模块的路径值。这样做的效果是将 Go 的模块搜索重定向到替换的位置。你不必更改包的导入路径以使用替换路径。
在构建当前模块时,使用exclude和replace指令来控制构建时的依赖项解析。这些指令在依赖于当前模块的模块中会被忽略。
replace指令在以下情况下很有用:
- 你正在开发一个新的模块,其代码还没有进入存储库。你想用一个本地版本的客户端进行测试。
- 你发现了一个依赖项的问题,克隆了这个依赖项的存储库,并且正在使用本地存储库测试一个修复程序。
!!! warning “请注意”
请注意,单独的`replace`指令并不能将一个模块添加到[module graph(模块图)](../GoModulesReference/Glossary#module-graph)中。在主模块的 `go.mod` 文件或依赖模块的 `go.mod` 文件中,还需要一个指向被替换模块版本的 [require 指令](#require)。如果你没有一个特定的版本要替换,你可以使用一个假版本,就像下面的示例。注意,这将破坏依赖于你的模块的模块,因为`replace`指令仅应用于主模块。
require example.com/mod v0.0.0-replace
replace example.com/mod v0.0.0-replace => ./mod
关于替换所需模块的更多信息,包括使用Go工具进行更改,请参见:
- Requiring external module code from your own repository fork(从你自己的版本库分叉中请求外部模块代码)
- Requiring module code in a local directory(要求本地目录中的模块代码)
更多关于版本号的信息,参见模块版本号。
exclude 排除
指定要从当前模块的依赖关系图中排除的模块或模块版本。
更多信息请参见 Go Modules Reference 中的 exclude 指令。
Syntax 语法
exclude module-path module-version
-
module-path
要排除的模块的模块路径。
-
module-version
要排除的特定版本。
Example 示例
-
排除 example.com/theirmodule 版本
v1.3.0exclude example.com/theirmodule v1.3.0
Notes 注意事项
使用exclude指令可以排除一个间接需要但由于某种原因无法加载的模块的特定版本。例如,你可以用它来排除一个有无效校验和的模块的版本。
在构建当前模块(你正在构建的主模块)时,使用exclude和replace指令来控制构建时的依赖项解析。这些指令在依赖于当前模块的模块中会被忽略。
你可以使用go mod edit命令来排除一个模块,如下面的示例。
go mod edit -exclude=example.com/theirmodule@v1.3.0
更多关于版本号的信息,请参见模块版本号。
retract 撤回
指示不应依赖go.mod定义的模块的版本或版本范围。当版本提前发布或在发布后发现严重问题时,retract指令很有用。
更多信息请参见 Go Modules Reference 中的 retract 指令。
Syntax 语法
retract version // rationale
retract [version-low,version-high] // rationale
-
version
要撤回的单个版本。
-
version-low
要撤回的版本范围的下限。
-
version-high
要撤回的版本范围的上限。版本-低和版本-高都包括在这个范围内。
-
rationale
解释撤回的可选注释。可以在发给用户的消息中显示。
Example 示例
-
Retracting a single version 撤回单个版本
retract v1.1.0 // Published accidentally. -
Retracting a range of versions 撤回一系列的版本
retract [v1.0.0,v1.0.5] // Build broken on some platforms.
Notes 注意事项
使用retract指令来指示你的模块的前一个版本不应该被使用。用户不会通过go get、go mod tidy或其他命令自动升级到撤回的版本。用户不会在go list -m -u中看到撤回的版本是可用的更新。
撤回的版本应该保持可用,以便已经依赖它们的用户能够构建他们的软件包。即使撤回的版本已经从源码库中删除,它仍然可以在proxy.golang.org这样的镜像中使用。当用户在相关模块上运行 go get 或 go list -m -u 时,他们可能会被通知依赖被撤回的版本。
go命令通过读取模块最新版本的go.mod文件中的retract指令来发现撤回的版本。最新的版本是,按优先顺序排列:
- 它的最高发布版本,如果有的话;
- 它的最高预发布版本,如果有的话;
- 储存库默认分支的尖端(tip)的伪版本。
当你添加一个撤回内容时,你几乎总是需要标记一个新的、更高的版本,这样命令就会在模块的最新版本中看到它。
你可以发布一个版本,该版本的唯一目的是发出撤回的信号。在这种情况下,新版本也可能撤回自己。
例如,如果你不小心标记了v1.0.0,你可以用以下指令标记v1.0.1:
retract v1.0.0 // Published accidentally. 已意外地发布。
retract v1.0.1 // Contains retraction only. 仅包含撤回。
遗憾的是,一旦版本发布,就无法更改。如果稍后在不同的提交中标记了v1.0.0,go命令可能会在go.sum或校验数据库中检测到一个不匹配的和。
模块的撤回版本通常不会出现在 go list -m -versions 的输出中,但你可以使用 -retracted 来显示它们。更多信息请参见 Go Modules Reference 中的 go list -m。
1.6 - Contribution Guide
Contribution Guide
The Go project welcomes all contributors.
This document is a guide to help you through the process of contributing to the Go project, which is a little different from that used by other open source projects. We assume you have a basic understanding of Git and Go.
In addition to the information here, the Go community maintains a CodeReview wiki page. Feel free to contribute to the wiki as you learn the review process.
Note that the gccgo front end lives elsewhere; see Contributing to gccgo.
Becoming a contributor
Overview
The first step is registering as a Go contributor and configuring your environment. Here is a checklist of the required steps to follow:
- Step 0: Decide on a single Google Account you will be using to contribute to Go. Use that account for all the following steps and make sure that
gitis configured to create commits with that account’s e-mail address. - Step 1: Sign and submit a CLA (Contributor License Agreement).
- Step 2: Configure authentication credentials for the Go Git repository. Visit go.googlesource.com, click “Generate Password” in the page’s top right menu bar, and follow the instructions.
- Step 3: Register for Gerrit, the code review tool used by the Go team, by visiting this page. The CLA and the registration need to be done only once for your account.
- Step 4: Install
git-codereviewby runninggo install golang.org/x/review/git-codereview@latest
If you prefer, there is an automated tool that walks through these steps. Just run:
$ go install golang.org/x/tools/cmd/go-contrib-init@latest
$ cd /code/to/edit
$ go-contrib-init
The rest of this chapter elaborates on these instructions. If you have completed the steps above (either manually or through the tool), jump to Before contributing code.
Step 0: Select a Google Account
A contribution to Go is made through a Google account with a specific e-mail address. Make sure to use the same account throughout the process and for all your subsequent contributions. You may need to decide whether to use a personal address or a corporate address. The choice will depend on who will own the copyright for the code that you will be writing and submitting. You might want to discuss this topic with your employer before deciding which account to use.
Google accounts can either be Gmail e-mail accounts, G Suite organization accounts, or accounts associated with an external e-mail address. For instance, if you need to use an existing corporate e-mail that is not managed through G Suite, you can create an account associated with your existing e-mail address.
You also need to make sure that your Git tool is configured to create commits using your chosen e-mail address. You can either configure Git globally (as a default for all projects), or locally (for a single specific project). You can check the current configuration with this command:
$ git config --global user.email # check current global config
$ git config user.email # check current local config
To change the configured address:
$ git config --global user.email name@example.com # change global config
$ git config user.email name@example.com # change local config
Step 1: Contributor License Agreement
Before sending your first change to the Go project you must have completed one of the following two CLAs. Which CLA you should sign depends on who owns the copyright to your work.
- If you are the copyright holder, you will need to agree to the individual contributor license agreement, which can be completed online.
- If your organization is the copyright holder, the organization will need to agree to the corporate contributor license agreement.
You can check your currently signed agreements and sign new ones at the Google Developers Contributor License Agreements website. If the copyright holder for your contribution has already completed the agreement in connection with another Google open source project, it does not need to be completed again.
If the copyright holder for the code you are submitting changes—for example, if you start contributing code on behalf of a new company—please send mail to the golang-dev mailing list. This will let us know the situation so we can make sure an appropriate agreement is completed.
Step 2: Configure git authentication
The main Go repository is located at go.googlesource.com, a Git server hosted by Google. Authentication on the web server is made through your Google account, but you also need to configure git on your computer to access it. Follow these steps:
- Visit go.googlesource.com and click on “Generate Password” in the page’s top right menu bar. You will be redirected to accounts.google.com to sign in.
- After signing in, you will be taken to a page with the title “Configure Git”. This page contains a personalized script that when run locally will configure Git to hold your unique authentication key. This key is paired with one that is generated and stored on the server, analogous to how SSH keys work.
- Copy and run this script locally in your terminal to store your secret authentication token in a
.gitcookiesfile. If you are using a Windows computer and runningcmd, you should instead follow the instructions in the yellow box to run the command; otherwise run the regular script.
Step 3: Create a Gerrit account
Gerrit is an open-source tool used by Go maintainers to discuss and review code submissions.
To register your account, visit go-review.googlesource.com/login/ and sign in once using the same Google Account you used above.
Step 4: Install the git-codereview command
Changes to Go must be reviewed before they are accepted, no matter who makes the change. A custom git command called git-codereview simplifies sending changes to Gerrit.
Install the git-codereview command by running,
$ go install golang.org/x/review/git-codereview@latest
Make sure git-codereview is installed in your shell path, so that the git command can find it. Check that
$ git codereview help
prints help text, not an error. If it prints an error, make sure that $GOPATH/bin is in your $PATH.
On Windows, when using git-bash you must make sure that git-codereview.exe is in your git exec-path. Run git --exec-path to discover the right location then create a symbolic link or just copy the executable from $GOPATH/bin to this directory.
Before contributing code
The project welcomes code patches, but to make sure things are well coordinated you should discuss any significant change before starting the work. It’s recommended that you signal your intention to contribute in the issue tracker, either by filing a new issue or by claiming an existing one.
Where to contribute
The Go project consists of the main go repository, which contains the source code for the Go language, as well as many golang.org/x/… repositories. These contain the various tools and infrastructure that support Go. For example, golang.org/x/pkgsite is for pkg.go.dev, golang.org/x/playground is for the Go playground, and golang.org/x/tools contains a variety of Go tools, including the Go language server, gopls. You can see a list of all the golang.org/x/… repositories on go.googlesource.com.
Check the issue tracker
Whether you already know what contribution to make, or you are searching for an idea, the issue tracker is always the first place to go. Issues are triaged to categorize them and manage the workflow.
The majority of the golang.org/x/… repos also use the main Go issue tracker. However, a few of these repositories manage their issues separately, so please be sure to check the right tracker for the repository to which you would like to contribute.
Most issues will be marked with one of the following workflow labels:
- NeedsInvestigation: The issue is not fully understood and requires analysis to understand the root cause.
- NeedsDecision: the issue is relatively well understood, but the Go team hasn’t yet decided the best way to address it. It would be better to wait for a decision before writing code. If you are interested in working on an issue in this state, feel free to “ping” maintainers in the issue’s comments if some time has passed without a decision.
- NeedsFix: the issue is fully understood and code can be written to fix it.
You can use GitHub’s search functionality to find issues to help out with. Examples:
- Issues that need investigation:
is:issue is:open label:NeedsInvestigation - Issues that need a fix:
is:issue is:open label:NeedsFix - Issues that need a fix and have a suggested change:
is:issue is:open label:NeedsFix "golang.org/cl" - Issues that need a fix and do not have a suggested change:
is:issue is:open label:NeedsFix NOT "golang.org/cl"
Open an issue for any new problem
Excluding very trivial changes, all contributions should be connected to an existing issue. Feel free to open one and discuss your plans. This process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside the goals for the language and tools. It also checks that the design is sound before code is written; the code review tool is not the place for high-level discussions.
When planning work, please note that the Go project follows a six-month development cycle for the main Go repository. The latter half of each cycle is a three-month feature freeze during which only bug fixes and documentation updates are accepted. New contributions can be sent during a feature freeze, but they will not be merged until the freeze is over. The freeze applies to the entire main repository as well as to the code in golang.org/x/… repositories that is needed to build the binaries included in the release. See the lists of packages vendored into the standard library and the go command.
Significant changes to the language, libraries, or tools must go through the change proposal process before they can be accepted.
Sensitive security-related issues (only!) should be reported to security@golang.org.
Sending a change via GitHub
First-time contributors that are already familiar with the GitHub flow are encouraged to use the same process for Go contributions. Even though Go maintainers use Gerrit for code review, a bot called Gopherbot has been created to sync GitHub pull requests to Gerrit.
Open a pull request as you normally would. Gopherbot will create a corresponding Gerrit change and post a link to it on your GitHub pull request; updates to the pull request will also get reflected in the Gerrit change. When somebody comments on the change, their comment will be also posted in your pull request, so you will get a notification.
Some things to keep in mind:
- To update the pull request with new code, just push it to the branch; you can either add more commits, or rebase and force-push (both styles are accepted).
- If the request is accepted, all commits will be squashed, and the final commit description will be composed by concatenating the pull request’s title and description. The individual commits’ descriptions will be discarded. See Writing good commit messages for some suggestions.
- Gopherbot is unable to sync line-by-line codereview into GitHub: only the contents of the overall comment on the request will be synced. Remember you can always visit Gerrit to see the fine-grained review.
Sending a change via Gerrit
It is not possible to fully sync Gerrit and GitHub, at least at the moment, so we recommend learning Gerrit. It’s different but powerful and familiarity with it will help you understand the flow.
Overview
This is an overview of the overall process:
-
Step 1:
Clone the source code from
go.googlesource.comand make sure it’s stable by compiling and testing it once.
If you’re making a change to the main Go repository:
$ git clone https://go.googlesource.com/go $ cd go/src $ ./all.bash # compile and testIf you’re making a change to one of the golang.org/x/… repositories (golang.org/x/tools, in this example):
$ git clone https://go.googlesource.com/tools $ cd tools $ go test ./... # compile and test -
Step 2:
Prepare changes in a new branch, created from the master branch. To commit the changes, use
gitcodereviewchange; that will create or amend a single commit in the branch.
$ git checkout -b mybranch $ [edit files...] $ git add [files...] $ git codereview change # create commit in the branch $ [edit again...] $ git add [files...] $ git codereview change # amend the existing commit with new changes $ [etc.] -
Step 3:
Test your changes, either by running the tests in the package you edited or by re-running
all.bash.
In the main Go repository:
$ ./all.bash # recompile and testIn a golang.org/x/… repository:
$ go test ./... # recompile and test -
Step 4:
Send the changes for review to Gerrit using
gitcodereviewmail(which doesn’t use e-mail, despite the name).
$ git codereview mail # send changes to Gerrit -
Step 5:
After a review, apply changes to the same single commit and mail them to Gerrit again:
$ [edit files...] $ git add [files...] $ git codereview change # update same commit $ git codereview mail # send to Gerrit again
The rest of this section describes these steps in more detail.
Step 1: Clone the source code
In addition to a recent Go installation, you need to have a local copy of the source checked out from the correct repository. You can check out the Go source repo onto your local file system anywhere you want as long as it’s outside your GOPATH. Clone from go.googlesource.com (not GitHub):
Main Go repository:
$ git clone https://go.googlesource.com/go
$ cd go
golang.org/x/… repository
(golang.org/x/tools in this example):
$ git clone https://go.googlesource.com/tools
$ cd tools
Step 2: Prepare changes in a new branch
Each Go change must be made in a separate branch, created from the master branch. You can use the normal git commands to create a branch and add changes to the staging area:
$ git checkout -b mybranch
$ [edit files...]
$ git add [files...]
To commit changes, instead of git commit, use git codereview change.
$ git codereview change
(open $EDITOR)
You can edit the commit description in your favorite editor as usual. The git codereview change command will automatically add a unique Change-Id line near the bottom. That line is used by Gerrit to match successive uploads of the same change. Do not edit or delete it. A Change-Id looks like this:
Change-Id: I2fbdbffb3aab626c4b6f56348861b7909e3e8990
The tool also checks that you’ve run go fmt over the source code, and that the commit message follows the suggested format.
If you need to edit the files again, you can stage the new changes and re-run git codereview change: each subsequent run will amend the existing commit while preserving the Change-Id.
Make sure that you always keep a single commit in each branch. If you add more commits by mistake, you can use git rebase to squash them together into a single one.
Step 3: Test your changes
You’ve written and tested your code, but before sending code out for review, run all the tests for the whole tree to make sure the changes don’t break other packages or programs.
In the main Go repository
This can be done by running all.bash:
$ cd go/src
$ ./all.bash
(To build under Windows use all.bat)
After running for a while and printing a lot of testing output, the command should finish by printing,
ALL TESTS PASSED
You can use make.bash instead of all.bash to just build the compiler and the standard library without running the test suite. Once the go tool is built, it will be installed as bin/go under the directory in which you cloned the Go repository, and you can run it directly from there. See also the section on how to test your changes quickly.
In the golang.org/x/… repositories
Run the tests for the entire repository (golang.org/x/tools, in this example):
$ cd tools
$ go test ./...
If you’re concerned about the build status, you can check the Build Dashboard. Test failures may also be caught by the TryBots in code review.
Some repositories, like golang.org/x/vscode-go will have different testing infrastructures, so always check the documentation for the repository in which you are working. The README file in the root of the repository will usually have this information.
Step 4: Send changes for review
Once the change is ready and tested over the whole tree, send it for review. This is done with the mail sub-command which, despite its name, doesn’t directly mail anything; it just sends the change to Gerrit:
$ git codereview mail
Gerrit assigns your change a number and URL, which git codereview mail will print, something like:
remote: New Changes:
remote: https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments
If you get an error instead, check the Troubleshooting mail errors section.
If your change relates to an open GitHub issue and you have followed the suggested commit message format, the issue will be updated in a few minutes by a bot, linking your Gerrit change to it in the comments.
Step 5: Revise changes after a review
Go maintainers will review your code on Gerrit, and you will get notifications via e-mail. You can see the review on Gerrit and comment on them there. You can also reply using e-mail if you prefer.
If you need to revise your change after the review, edit the files in the same branch you previously created, add them to the Git staging area, and then amend the commit with git codereview change:
$ git codereview change # amend current commit
(open $EDITOR)
$ git codereview mail # send new changes to Gerrit
If you don’t need to change the commit description, just save and exit from the editor. Remember not to touch the special Change-Id line.
Again, make sure that you always keep a single commit in each branch. If you add more commits by mistake, you can use git rebase to squash them together into a single one.
Good commit messages
Commit messages in Go follow a specific set of conventions, which we discuss in this section.
Here is an example of a good one:
math: improve Sin, Cos and Tan precision for very large arguments
The existing implementation has poor numerical properties for
large arguments, so use the McGillicutty algorithm to improve
accuracy above 1e10.
The algorithm is described at https://wikipedia.org/wiki/McGillicutty_Algorithm
Fixes #159
First line
The first line of the change description is conventionally a short one-line summary of the change, prefixed by the primary affected package.
A rule of thumb is that it should be written so to complete the sentence “This change modifies Go to _____.” That means it does not start with a capital letter, is not a complete sentence, and actually summarizes the result of the change.
Follow the first line by a blank line.
Main content
The rest of the description elaborates and should provide context for the change and explain what it does. Write in complete sentences with correct punctuation, just like for your comments in Go. Don’t use HTML, Markdown, or any other markup language.
Add any relevant information, such as benchmark data if the change affects performance. The benchstat tool is conventionally used to format benchmark data for change descriptions.
Referencing issues
The special notation “Fixes #12345” associates the change with issue 12345 in the Go issue tracker. When this change is eventually applied, the issue tracker will automatically mark the issue as fixed.
If the change is a partial step towards the resolution of the issue, write “Updates #12345” instead. This will leave a comment in the issue linking back to the change in Gerrit, but it will not close the issue when the change is applied.
If you are sending a change against a golang.org/x/… repository, you must use the fully-qualified syntax supported by GitHub to make sure the change is linked to the issue in the main repository, not the x/ repository. Most issues are tracked in the main repository’s issue tracker. The correct form is “Fixes golang/go#159”.
The review process
This section explains the review process in detail and how to approach reviews after a change has been mailed.
Common beginner mistakes
When a change is sent to Gerrit, it is usually triaged within a few days. A maintainer will have a look and provide some initial review that for first-time contributors usually focuses on basic cosmetics and common mistakes. These include things like:
- Commit message not following the suggested format.
- The lack of a linked GitHub issue. The vast majority of changes require a linked issue that describes the bug or the feature that the change fixes or implements, and consensus should have been reached on the tracker before proceeding with it. Gerrit reviews do not discuss the merit of the change, just its implementation. Only trivial or cosmetic changes will be accepted without an associated issue.
- Change sent during the freeze phase of the development cycle, when the tree is closed for general changes. In this case, a maintainer might review the code with a line such as
R=go1.12, which means that it will be reviewed later when the tree opens for a new development window. You can addR=go1.XXas a comment yourself if you know that it’s not the correct time frame for the change.
Trybots
After an initial reading of your change, maintainers will trigger trybots, a cluster of servers that will run the full test suite on several different architectures. Most trybots complete in a few minutes, at which point a link will be posted in Gerrit where you can see the results.
If the trybot run fails, follow the link and check the full logs of the platforms on which the tests failed. Try to understand what broke, update your patch to fix it, and upload again. Maintainers will trigger a new trybot run to see if the problem was fixed.
Sometimes, the tree can be broken on some platforms for a few hours; if the failure reported by the trybot doesn’t seem related to your patch, go to the Build Dashboard and check if the same failure appears in other recent commits on the same platform. In this case, feel free to write a comment in Gerrit to mention that the failure is unrelated to your change, to help maintainers understand the situation.
Reviews
The Go community values very thorough reviews. Think of each review comment like a ticket: you are expected to somehow “close” it by acting on it, either by implementing the suggestion or convincing the reviewer otherwise.
After you update the change, go through the review comments and make sure to reply to every one. You can click the “Done” button to reply indicating that you’ve implemented the reviewer’s suggestion; otherwise, click on “Reply” and explain why you have not, or what you have done instead.
It is perfectly normal for changes to go through several round of reviews, with one or more reviewers making new comments every time and then waiting for an updated change before reviewing again. This cycle happens even for experienced contributors, so don’t be discouraged by it.
Voting conventions
As they near a decision, reviewers will apply a Code-Review “vote” to your change. There are two possible votes:
- +2 The change is approved for being merged. Only Go maintainers (also referred to as “approvers”) can cast a +2 vote.
- +1 The change looks good, but either the reviewer is requesting minor changes before approving it, or they are not a maintainer and cannot approve it, but would like to encourage an approval.
To be submitted, a change must have a Code-Review +2 from a maintainer.
Maintainers can also apply a Hold +1 vote to the change, to mark a change that should not be submitted now (for example, because the proposal review for new API in the change has not completed).
To be submitted, a change must not have any Hold +1 votes from a maintainer.
Finally, to be submitted, a change must have the involvement of two Google employees, either as the uploader of the change or as a reviewer voting at least Code-Review +1. This requirement is for compliance and supply chain security reasons.
Submitting an approved change
When a change is ready, a maintainer will submit the change, which adds it as a commit to the Gerrit repository.
The two steps (approving and submitting) are separate because in some cases maintainers may want to approve it but not to submit it right away (for instance, the tree could be temporarily frozen).
Submitting a change checks it into the repository. The change description will include a link to the code review, which will be updated with a link to the change in the repository. Since the method used to integrate the changes is Git’s “Cherry Pick”, the commit hashes in the repository will be changed by the submit operation.
If your change has been approved for a few days without being submitted, feel free to write a comment in Gerrit requesting submission.
More information
In addition to the information here, the Go community maintains a CodeReview wiki page. Feel free to contribute to this page as you learn more about the review process.
Miscellaneous topics
This section collects a number of other comments that are outside the issue/edit/code review/submit process itself.
Copyright headers
Files in the Go repository don’t list author names, both to avoid clutter and to avoid having to keep the lists up to date. Instead, your name will appear in the change log.
New files that you contribute should use the standard copyright header:
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
Files in the repository are copyrighted the year they are added. Do not update the copyright year on files that you change.
Troubleshooting mail errors
The most common way that the git codereview mail command fails is because the e-mail address in the commit does not match the one that you used during the registration process.
If you see something like…
remote: Processing changes: refs: 1, done
remote:
remote: ERROR: In commit ab13517fa29487dcf8b0d48916c51639426c5ee9
remote: ERROR: author email address XXXXXXXXXXXXXXXXXXX
remote: ERROR: does not match your user account.
you need to configure Git for this repository to use the e-mail address that you registered with. To change the e-mail address to ensure this doesn’t happen again, run:
$ git config user.email email@address.com
Then change the commit to use this alternative e-mail address with this command:
$ git commit --amend --author="Author Name <email@address.com>"
Then retry by running:
$ git codereview mail
Quickly testing your changes
Running all.bash for every single change to the code tree is burdensome. Even though it is strongly suggested to run it before sending a change, during the normal development cycle you may want to compile and test only the package you are developing.
-
In general, you can run
make.bashinstead ofall.bashto only rebuild the Go tool chain without running the whole test suite. Or you can runrun.bashto only run the whole test suite without rebuilding the tool chain. You can think ofall.bashasmake.bashfollowed byrun.bash. -
In this section, we’ll call the directory into which you cloned the Go repository
$GOROOT. The
gotool built by
$GOROOT/src/make.bashwill be installed in
$GOROOT/bin/goand you can invoke it to test your code. For instance, if you have modified the compiler and you want to test how it affects the test suite of your own project, just run
gotestusing it:
$ cd <MYPROJECTDIR> $ $GOROOT/bin/go test -
If you’re changing the standard library, you probably don’t need to rebuild the compiler: you can just run the tests for the package you’ve changed. You can do that either with the Go version you normally use, or with the Go compiler built from your clone (which is sometimes required because the standard library code you’re modifying might require a newer version than the stable one you have installed).
$ cd $GOROOT/src/crypto/sha1 $ [make changes...] $ $GOROOT/bin/go test . -
If you’re modifying the compiler itself, you can just recompile the
compiletool (which is the internal binary invoked by
gobuildto compile each single package). After that, you will want to test it by compiling or running something.
$ cd $GOROOT/src $ [make changes...] $ $GOROOT/bin/go install cmd/compile $ $GOROOT/bin/go build [something...] # test the new compiler $ $GOROOT/bin/go run [something...] # test the new compiler $ $GOROOT/bin/go test [something...] # test the new compilerThe same applies to other internal tools of the Go tool chain, such as
asm,
cover,
link, and so on. Just recompile and install the tool using
goinstallcmd/<TOOL>and then use the built Go binary to test it.
-
In addition to the standard per-package tests, there is a top-level test suite in
$GOROOT/testthat contains several black-box and regression tests. The test suite is run by
all.bashbut you can also run it manually:
$ cd $GOROOT/test $ $GOROOT/bin/go run run.go
Specifying a reviewer / CCing others
Unless explicitly told otherwise, such as in the discussion leading up to sending in the change, it’s better not to specify a reviewer. All changes are automatically CC’ed to the golang-codereviews@googlegroups.com mailing list. If this is your first ever change, there may be a moderation delay before it appears on the mailing list, to prevent spam.
You can specify a reviewer or CC interested parties using the -r or -cc options. Both accept a comma-separated list of e-mail addresses:
$ git codereview mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
Synchronize your client
While you were working, others might have submitted changes to the repository. To update your local branch, run
$ git codereview sync
(Under the covers this runs git pull -r.)
Reviewing code by others
As part of the review process reviewers can propose changes directly (in the GitHub workflow this would be someone else attaching commits to a pull request). You can import these changes proposed by someone else into your local Git repository. On the Gerrit review page, click the “Download ▼” link in the upper right corner, copy the “Checkout” command and run it from your local Git repo. It will look something like this:
$ git fetch https://go.googlesource.com/review refs/changes/21/13245/1 && git checkout FETCH_HEAD
To revert, change back to the branch you were working in.
Set up git aliases
The git-codereview command can be run directly from the shell by typing, for instance,
$ git codereview sync
but it is more convenient to set up aliases for git-codereview’s own subcommands, so that the above becomes,
$ git sync
The git-codereview subcommands have been chosen to be distinct from Git’s own, so it’s safe to define these aliases. To install them, copy this text into your Git configuration file (usually .gitconfig in your home directory):
[alias]
change = codereview change
gofmt = codereview gofmt
mail = codereview mail
pending = codereview pending
submit = codereview submit
sync = codereview sync
Sending multiple dependent changes
Advanced users may want to stack up related commits in a single branch. Gerrit allows for changes to be dependent on each other, forming such a dependency chain. Each change will need to be approved and submitted separately but the dependency will be visible to reviewers.
To send out a group of dependent changes, keep each change as a different commit under the same branch, and then run:
$ git codereview mail HEAD
Make sure to explicitly specify HEAD, which is usually not required when sending single changes. More details can be found in the git-codereview documentation.
1.7 - Release History
Release History
本页总结了Go官方稳定版本之间的变化。变更日志中有完整的细节。
要更新到一个特定的版本,请使用:
git fetch --tags
git checkout goX.Y.Z
Release Policy 发布政策
每个主要的 Go 版本都被支持,直到有两个更新的主要版本。例如,Go 1.5 被支持到 Go 1.7 发布,而 Go 1.6 被支持到 Go 1.8 发布。我们会根据需要通过发布小修订版(例如,Go 1.6.1、Go 1.6.2,等等)来修复支持的版本中的关键问题,包括关键的安全问题(critical security problems)。
go1.20 (released 2023-02-01)
Go 1.20 is a major release of Go. Read the Go 1.20 Release Notes for more information.
go 1.20是Go的一个重要版本。请阅读 Go 1.20 发行说明了解更多信息。
Minor revisions
go1.20.1 (released 2023-02-14) includes security fixes to the crypto/tls, mime/multipart, net/http, and path/filepath packages, as well as bug fixes to the compiler, the go command, the linker, the runtime, and the time package. See the Go 1.20.1 milestone on our issue tracker for details.
go1.20.1(2023-02-14发布)包括对crypto/tls、mime/multipart、net/http和path/filepath包的安全修正,以及对编译器、go命令、链接器、runtime和time包的错误修正。详情请见我们问题跟踪器上的Go 1.20.1 milestone。
go1.19 (released 2022-08-02)
Go 1.19是Go的一个主要版本。请阅读 Go 1.19 发行说明了解更多信息。
Minor revisions
go1.19.1(2022-09-06发布)包括对net/http和net/url包的安全修复,以及对编译器、go命令、pprof命令、链接器、runtime和crypto/tls和crypto/x509包的错误修复。详情请见我们问题跟踪器上的 Go 1.19.1 milestone。
go1.19.2(2022-10-04发布)包括对archive/tar、net/http/httputil和regexp包的安全修复,以及对编译器、链接器、runtime和go/types包的错误修复。详情请见我们问题跟踪器上的Go 1.19.2 milestone。
go1.19.3(2022-11-01发布)包括对os/exec和syscall包的安全修复,以及对编译器和runtime的错误修复。详情请见我们问题跟踪器上的 Go 1.19.3 milestone。
go1.19.4(2022-12-06发布)包括对net/http和os包的安全修复,以及对编译器、runtime、crypto/x509、os/exec和sync/atomic包的错误修复。详情请见我们问题跟踪器上的 Go 1.19.4 milestone。
go1.18 (released 2022-03-15)
Go 1.18是Go的一个重要版本。阅读 Go 1.18 发行说明以了解更多信息。
Minor revisions
go1.18.1(2022-04-12发布)包括对crypto/elliptic、crypto/x509和encoding/pem包的安全修复,以及对编译器、链接器、runtime、go命令、vet以及bytes、crypto/x509和go/types包的错误修复。详情请见我们问题跟踪器上的 Go 1.18.1 milestone。
go1.18.2(2022-05-10发布)包括对syscall包的安全修复,以及对编译器、runtime、go命令和crypto/x509、go/types、net/http/httptest、reflect和sync/atomic包的错误修复。详情请见我们问题跟踪器上的Go 1.18.2 milestone。
go1.18.3(2022-06-01发布)包括对crypto/rand、crypto/tls、os/exec和path/filepath包的安全修复,以及对编译器、crypto/tls和text/template/parse包的错误修复。详情请见我们问题跟踪器上的Go 1.18.3 milestone。
go1.18.4(2022-07-12发布)包括对compress/gzip、encoding/gob、encoding/xml、go/parser、io/fs、net/http和path/filepath包的安全修复,以及对编译器、go命令、链接器、runtime和runtime/计量包的错误修复。详情请见我们问题跟踪器上的Go 1.18.4 milestone。
go1.18.5(2022-08-01发布)包括encoding/gob和math/big包的安全修复,以及编译器、go命令、runtime和testing包的错误修复。详情请见我们问题跟踪器上的Go 1.18.5 milestone。
go1.18.6(2022-09-06发布)包括对net/http包的安全修复,以及对编译器、go命令、pprof命令、runtime以及crypto/tls、encoding/xml和net包的错误修复。详情请见我们问题跟踪器上的 Go 1.18.6 milestone。
go1.18.7(2022-10-04发布)包括对archive/tar、net/http/httputil和regexp包的安全修复,以及对编译器、链接器和go/types包的错误修复。详情请见我们问题跟踪器上的 Go 1.18.7 milestone。
go1.18.8(2022-11-01发布)包括对os/exec和syscall包的安全修复,以及对runtime的错误修复。详情请参见问题跟踪器上的 Go 1.18.8 milestone。
go1.17 (released 2021-08-16)
Go 1.17是Go的一个重要版本。阅读 Go 1.17 发行说明以了解更多信息。
Minor revisions
go1.17.1(2021-09-09发布)包括对archive/zip包的安全修复,以及对编译器、链接器、go命令和crypto/rand、embed、go/types、html/template和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.1 milestone。
go1.17.2(2021-10-07发布)包括对linker和misc/wasm目录的安全修复,以及对编译器、runtime、go命令、text/template和time包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.2 milestone。
go1.17.3(2021-11-04发布)包括对archive/zip和debug/macho包的安全修复,以及对编译器、链接器、runtime、go命令、misc/wasm目录以及net/http和syscall包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.3 milestone。
go1.17.4(2021-12-02发布)包括对编译器、链接器、runtime以及go/types、net/http和time包的修复。详情请参见问题追踪器上的Go 1.17.4 milestone。
go1.17.5(2021-12-09发布)包括net/http和syscall包的安全修复。详情请参见问题追踪器上的Go 1.17.5 milestone。
go1.17.6 (2022-01-06发布) 包括对编译器、链接器、runtime以及 crypto/x509、net/http 和 reflect 包的修复。详情请参见问题跟踪器上的 Go 1.17.6 milestone。
go1.17.7(2022-02-10发布)包括对go命令、crypto/elliptic和math/big包的安全修复,以及对编译器、链接器、runtime、go命令和debug/macho、debug/pe、net/http/httptest包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.7 milestone。
go1.17.8(2022-03-03发布)包括对regexp/syntax包的安全修复,以及对编译器、runtime、go命令以及crypto/x509和net包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.8 milestone。
go1.17.9(2022-04-12发布)包括对crypto/elliptic和encoding/pem包的安全修复,以及对链接器和runtime的错误修复。详情请参见问题跟踪器上的 Go 1.17.9 milestone。
go1.17.10 (2022-05-10发布) 包括对syscall包的安全修复,以及对编译器、runtime、crypto/x509和net/http/httptest包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.10 milestone。
go1.17.11(2022-06-01发布)包括对crypto/rand、crypto/tls、os/exec和path/filepath包的安全修复,以及对crypto/tls包的错误修复。详情请见我们问题跟踪器上的 Go 1.17.11 milestone。
go1.17.12(2022-07-12发布)包括对compress/gzip、encoding/gob、encoding/xml、go/parser、io/fs、net/http和path/filepath包的安全修复,以及对编译器、go命令、runtime和runtime/metrics包的错误修复。详情请见我们的问题跟踪器上的 Go 1.17.12 milestone。
go1.17.13(2022-08-01发布)包括encoding/gob和math/big包的安全修复,以及编译器和runtime的错误修复。详情请参见问题跟踪器上的Go 1.17.13 milestone。
go1.16 (released 2021-02-16)
Go 1.16是Go的一个重要版本。请阅读 Go 1.16 发行说明以了解更多信息。
Minor revisions
go1.16.1(2021-03-10发布)包括对archive/zip和encoding/xml包的安全修复。详情请见我们问题追踪器上的 Go 1.16.1 milestone。
go1.16.2(2021-03-11发布)包括对cgo、编译器、链接器、go命令、以及syscall和time包的修复。详情请参见问题追踪器上的 Go 1.16.2 milestone。
go1.16.3(2021-04-01发布)包括对编译器、链接器、runtime、go命令以及testing和time包的修复。详情请参见问题跟踪器上的 Go 1.16.3 milestone。
go1.16.4(2021-05-06发布)包括对net/http包的安全修复,以及对编译器、runtime、archive/zip、syscall和time包的错误修复。详情请见我们问题跟踪器上的 Go 1.16.4 milestone。
go1.16.5(2021-06-03发布)包括对archive/zip、math/big、net和net/http/httputil包的安全修复,以及对链接器、go命令和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.16.5 milestone。
go1.16.6(2021-07-12发布)包括对crypto/tls包的安全修复,以及对编译器、net和net/http包的错误修复。详情请参见问题跟踪器上的Go 1.16.6 milestone。
go1.16.7(2021-08-05发布)包括对net/http/httputil包的安全修复,以及对编译器、链接器、runtime、go命令和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.16.7 milestone。
go1.16.8(2021-09-09发布)包括对archive/zip包的安全修复,以及对archive/zip、go/internal/gccgoimporter、html/template、net/http和runtime/pprof包的错误修复。详情请参见问题跟踪器上的 Go 1.16.8 milestone。
go1.16.9(2021-10-07发布)包括对linker和misc/wasm目录的安全修复,以及对runtime和text/template包的错误修复。详情请见我们问题跟踪器上的Go 1.16.9 milestone。
go1.16.10(2021-11-04发布)包括对archive/zip和debug/macho包的安全修复,以及对编译器、链接器、runtime、misc/wasm目录和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.16.10 milestone。
go1.16.11(2021-12-02发布)包括对编译器、runtime以及net/http、net/http/httptest和time包的修复。详情请参见问题跟踪器上的Go 1.16.11 milestone。
go1.16.12(2021-12-09发布)包括net/http和syscall包的安全修复。详情请参见问题追踪器上的Go 1.16.12 milestone。
go1.16.13(2022-01-06发布)包括对编译器、链接器、runtime和net/http包的修复。详情请参见问题追踪器上的 Go 1.16.13 milestone。
go1.16.14(2022-02-10发布)包括对go命令、crypto/elliptic和math/big包的安全修复,以及对编译器、链接器、runtime、go命令和debug/macho、debug/pe、net/http/httptest以及testing包的错误修复。详情请见我们问题跟踪器上的Go 1.16.14 milestone。
go1.16.15(2022-03-03发布)包括对regexp/syntax包的安全修复,以及对编译器、runtime、go命令和net包的错误修复。详情请见我们问题跟踪器上的Go 1.16.15 milestone。
go1.15 (released 2020-08-11)
Go 1.15是Go的一个重要版本。请阅读 Go 1.15 发行说明以了解更多信息。
Minor revisions
go1.15.1(2020-09-01发布)包括net/http/cgi和net/http/fcgi包的安全修复。详情请见我们问题跟踪器上的 Go 1.15.1 milestone。
go1.15.2(2020-09-09发布)包括对编译器、runtime、文档、go命令以及net/mail、os、sync和testing包的修复。详情请见我们问题跟踪器上的Go 1.15.2 milestone。
go1.15.3(2020-10-14发布)包括对cgo、编译器、runtime、go命令,以及bytes、plugin和testing包的修复。详情请见我们问题跟踪器上的Go 1.15.3 milestone。
go1.15.4(2020-11-05发布)包括对cgo、编译器、链接器、runtime,以及compress/flate、net/http、reflect和time包的修复。详情请见我们问题跟踪器上的Go 1.15.4 milestone。
go1.15.5(2020-11-12发布)包括对go命令和math/big包的安全修复。详情请参见问题追踪器上的Go 1.15.5 milestone。
go1.15.6(2020-12-03发布)包括对编译器、链接器、runtime、go命令和io包的修复。详情请参见问题追踪器上的Go 1.15.6 milestone。
go1.15.7(2021-01-19发布)包括对go命令和crypto/elliptic包的安全修复。详情请参见问题追踪器上的Go 1.15.7 milestone。
go1.15.8(2021-02-04发布)包括对编译器、链接器、runtime、go命令和net/http包的修复。详情请参见问题跟踪器上的 Go 1.15.8 milestone。
go1.15.9(2021-03-10发布)包括对encoding/xml包的安全修复。详见问题追踪器上的Go 1.15.9 milestone。
go1.15.10(2021-03-11发布)包括对编译器、go命令以及net/http、os、syscall和time包的修复。详情请参见问题跟踪器上的Go 1.15.10 milestone。
go1.15.11(2021-04-01发布)包括对cgo、编译器、链接器、runtime、go命令以及database/sql和net/http包的修复。详情请见我们问题跟踪器上的Go 1.15.11 milestone。
go1.15.12(2021-05-06发布)包括net/http包的安全修复,以及编译器、runtime、archive/zip、syscall和time包的错误修复。详情请见我们问题跟踪器上的 Go 1.15.12 milestone。
go1.15.13(2021-06-03发布)包括对archive/zip、math/big、net和net/http/httputil包的安全修复,以及对链接器、go命令、math/big和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.15.13 milestone。
go1.15.14(2021-07-12发布)包括对crypto/tls包的安全修复,以及对链接器和net包的错误修复。详情请参见问题跟踪器上的Go 1.15.14 milestone。
go1.15.15(2021-08-05发布)包括对net/http/httputil包的安全修复,以及对编译器、runtime、go命令和net/http包的错误修复。详情请见我们问题跟踪器上的Go 1.15.15 milestone。
go1.14 (released 2020-02-25)
Go 1.14是Go的一个重要版本。请阅读 Go 1.14 发行说明以了解更多信息。
Minor revisions
go1.14.1(2020-03-19发布)包括对go命令、工具和runtime的修正。请参阅我们问题跟踪器上的 Go 1.14.1 milestone以了解详情。
go1.14.2(2020-04-08发布)包括对cgo、go命令、runtime以及os/exec和testing包的修正。详情请参见问题追踪器上的 Go 1.14.2 milestone。
go1.14.3(2020-05-14发布)包括对cgo、编译器、runtime以及go/doc和math/big包的修正。详情请参见问题追踪器上的 Go 1.14.3 milestone。
go1.14.4(2020-06-01发布)包括对go doc命令、runtime、以及encoding/json和os包的修复。详情请参见问题追踪器上的 Go 1.14.4 milestone。
go1.14.5(2020-07-14发布)包括对crypto/x509和net/http包的安全修复。详情请参见问题追踪器上的 Go 1.14.5 milestone。
go1.14.6(2020-07-16发布)包括对go命令、编译器、链接器、vet以及database/sql、encoding/json、net/http、reflect和testing包的修复。详情请见我们的问题跟踪器上的 Go 1.14.6 milestone。
go1.14.7(2020-08-06发布)包括对encoding/binary包的安全修复。详见问题追踪器上的Go 1.14.7 milestone。
go1.14.8(2020-09-01发布)包括 net/http/cgi 和 net/http/fcgi 包的安全修复。详情请参见问题追踪器上的 Go 1.14.8 milestone。
go1.14.9(2020-09-09发布)包括对编译器、链接器、runtime、文档,以及net/http和testing包的修复。详情请参见问题跟踪器上的 Go 1.14.9 milestone。
go1.14.10(2020-10-14发布)包括对编译器、runtime以及plugin和testing包的修正。详情请参见问题追踪器上的Go 1.14.10 milestone。
go1.14.11(2020-11-05发布)包括对runtime、net/http和time包的修复。详情请参见问题追踪器上的 Go 1.14.11 milestone。
go1.14.12(2020-11-12发布)包括对go命令和math/big包的安全修复。详情请参见问题追踪器上的Go 1.14.12 milestone。
go1.14.13(2020-12-03发布)包括对编译器、runtime和go命令的修复。详情请参见问题追踪器上的Go 1.14.13 milestone。
go1.14.14(2021-01-19发布)包括对go命令和crypto/elliptic包的安全修复。详情请参见问题追踪器上的Go 1.14.14 milestone。
go1.14.15(2021-02-04发布)包括对编译器、runtime、go命令和net/http包的修复。详情请见我们问题追踪器上的Go 1.14.15 milestone。
go1.13 (released 2019-09-03)
Go 1.13是Go的一个重要版本。阅读 Go 1.13 发行说明以了解更多信息。
Minor revisions
go1.13.1(2019-09-25发布)包括net/http和net/textproto包的安全修复。详情请见我们问题跟踪器上的Go 1.13.1 milestone。
go1.13.2(2019-10-17发布)包括对编译器和crypto/dsa包的安全修复。详情请见我们问题追踪器上的Go 1.13.2 milestone。
go1.13.3(2019-10-17发布)包括对go命令、工具链、runtime以及crypto/ecdsa、net、net/http和syscall包的修复。详情请见我们问题跟踪器上的Go 1.13.3 milestone。
go1.13.4(2019-10-31发布)包括对net/http和syscall包的修复。它还修复了macOS 10.15 Catalina上的一个问题,即未经公证的安装程序和二进制文件被Gatekeeper拒绝。详情请见我们问题追踪器上的 Go 1.13.4 milestone。
go1.13.5(2019-12-04发布)包括对go命令、runtime、链接器和net/http包的修复。详情请见我们问题追踪器上的Go 1.13.5 milestone。
go1.13.6(2020-01-09发布)包括对runtime和net/http包的修正。详情请参见问题追踪器上的 Go 1.13.6 milestone。
go1.13.7(2020-01-28发布)包括对 crypto/x509 包的两个安全修复。详情请参见问题追踪器上的Go 1.13.7 milestone。
go1.13.8(2020-02-12发布)包括对runtime、crypto/x509和net/http包的修复。详情请参见问题追踪器上的 Go 1.13.8 milestone。
go1.13.9(2020-03-19发布)包括对go命令、工具、runtime、工具链和crypto/cypher包的修复。详情请见我们问题跟踪器上的Go 1.13.9 milestone。
go1.13.10(2020-04-08发布)包括对go命令、runtime以及os/exec和time包的修复。详情请参见问题追踪器上的 Go 1.13.10 milestone。
go1.13.11(2020-05-14发布)包括对编译器的修复。详见问题追踪器上的 Go 1.13.11 milestone。
go1.13.12(2020-06-01发布)包括对runtime以及go/types和math/big包的修正。详情请参见问题追踪器上的 Go 1.13.12 milestone。
go1.13.13(2020-07-14发布)包括对crypto/x509和net/http包的安全修复。详情请参见问题追踪器上的 Go 1.13.13 milestone。
go1.13.14(2020-07-16发布)包括对编译器、vet以及database/sql、net/http和reflect包的修复。详情请参见问题跟踪器上的 Go 1.13.14 milestone。
go1.13.15(2020-08-06发布)包括对encoding/binary包的安全修复。详情请见我们问题追踪器上的Go 1.13.15 milestone。
go1.12 (released 2019-02-25)
Go 1.12是Go的一个重要版本。阅读 Go 1.12 发行说明以了解更多信息。
Minor revisions
go1.12.1(2019-03-14发布)包括对cgo、编译器、go命令以及fmt、net/smtp、os、path/filepath、sync和text/template包的修正。详情请见我们问题跟踪器上的 Go 1.12.1 milestone。
go1.12.2(2019-04-05发布)包括对runtime的安全修复,以及对编译器、go命令、doc、net、net/http/httputil和os包的错误修复。详情请参见问题跟踪器上的 Go 1.12.2 milestone。
go1.12.3(2019-04-08发布)意外地在没有预定修复的情况下发布。它与go1.12.2相同,只是版本号不同。预定的修复在go1.12.4中。
go1.12.4(2019-04-11发布)修复了一个问题,即在旧版本的GNU/Linux上使用预编译的二进制版本会导致链接使用cgo的程序时出现故障。只有遇到这个问题的Linux用户才需要更新。
go1.12.5(2019-05-06发布)包括对编译器、链接器、go命令、runtime和os包的修复。详情请见我们问题跟踪器上的Go 1.12.5 milestone。
go1.12.6(2019-06-11发布)包括对编译器、链接器、go命令以及crypto/x509、net/http和os包的修复。详情请见我们问题跟踪器上的Go 1.12.6 milestone。
go1.12.7(2019-07-08发布)包括对cgo、编译器和链接器的修复。详情请见我们的问题跟踪器上的Go 1.12.7 milestone。
go1.12.8(2019-08-13发布)包括对net/http和net/url包的安全修复。详情请见我们问题追踪器上的Go 1.12.8 milestone。
go1.12.9(2019-08-15发布)包括对链接器以及math/big和os包的修复。详情请见我们问题追踪器上的Go 1.12.9里程碑。
go1.12.10(2019-09-25发布)包括对net/http和net/textproto包的安全修复。详情请见我们问题追踪器上的Go 1.12.10里程碑。
go1.12.11(2019-10-17发布)包括对crypto/dsa包的安全修复。详情请参见问题追踪器上的Go 1.12.11里程碑。
go1.12.12(2019-10-17发布)包括对go命令、runtime以及net和syscall包的修复。详情请见我们问题追踪器上的Go 1.12.12里程碑。
go1.12.13(2019-10-31发布)修复了macOS 10.15 Catalina上的一个问题,即未经公证的安装程序和二进制文件被Gatekeeper拒绝。只有遇到这个问题的macOS用户才需要更新。
go1.12.14(2019-12-04发布)包括一个对runtime的修复。详情请见我们问题跟踪器上的Go 1.12.14里程碑。
go1.12.15(2020-01-09发布)包括对runtime和net/http包的修复。详情请参见问题追踪器上的 Go 1.12.15 里程碑。
go1.12.16(2020-01-28发布)包括对 crypto/x509 包的两个安全修复。详情请参见问题追踪器上的 Go 1.12.16 里程碑。
go1.12.17(2020-02-12发布)包括一个对runtime的修复。详见问题追踪器上的Go 1.12.17里程碑。
go1.11 (released 2018-08-24)
Go 1.11是Go的一个重要版本。阅读 Go 1.11 发行说明以了解更多信息。
Minor revisions
go1.11.1(2018-10-01发布)包括对编译器、文档、go命令、runtime以及crypto/x509、encoding/json、go/types、net、net/http和reflect包的修复。详情请见我们问题跟踪器上的Go 1.11.1里程碑。
go1.11.2(2018-11-02发布)包括对编译器、链接器、文档、go命令,以及database/sql和go/types包的修复。详情请见我们问题跟踪器上的Go 1.11.2里程碑。
go1.11.3(2018-12-12发布)包括对 “go get“和crypto/x509包的三个安全修复。详情请见我们问题追踪器上的Go 1.11.3里程碑。
go1.11.4(2018-12-14发布)包括对cgo、编译器、链接器、runtime、文档、go命令以及go/types和net/http包的修复。它包括对Go 1.11.3中引入的一个bug的修复,该bug会破坏go get对于包含”...“的导入路径模式。详情请参见问题跟踪器上的 Go 1.11.4 里程碑。
go1.11.5(2019-01-23发布)包括一个对crypto/elliptic包的安全修复。详情请参见问题追踪器上的Go 1.11.5里程碑。
go1.11.6(2019-03-14发布)包括对cgo、编译器、链接器、runtime、go命令以及crypto/x509、encoding/json、net和net/url包的修复。详情请见我们问题跟踪器上的 Go 1.11.6 里程碑。
go1.11.7(2019-04-05发布)包括对runtime和net包的修复。详见问题追踪器上的Go 1.11.7里程碑。
go1.11.8(2019-04-08发布)是意外发布的,没有预定的修复。它与go1.11.7相同,只是版本号不同。预定的修复在go1.11.9中。
go1.11.9(2019-04-11发布)修复了一个问题,即在旧版本的GNU/Linux上使用预置二进制版本会导致链接使用cgo的程序时出现故障。只有遇到这个问题的Linux用户才需要更新。
go1.11.10(2019-05-06发布)包括对runtime的安全修复,以及对链接器的错误修复。详情请见我们问题跟踪器上的Go 1.11.10里程碑。
go1.11.11(2019-06-11发布)包括对crypto/x509包的修复。详情请见我们问题追踪器上的Go 1.11.11里程碑。
go1.11.12(2019-07-08发布)包括对编译器和链接器的修复。详见问题追踪器上的Go 1.11.12里程碑。
go1.11.13(2019-08-13发布)包括对net/http和net/url包的安全修复。详情请见我们的问题跟踪器上的Go 1.11.13里程碑。
go1.10 (released 2018-02-16)
Go 1.10是Go的一个重要版本。阅读 Go 1.10 发行说明以了解更多信息。
Minor revisions
go1.10.1(2018-03-28发布)包括对go命令的安全修复,以及对编译器、runtime和archive/zip、crypto/tls、crypto/x509、encoding/json、net、net/http和net/http/pprof包的错误修复。详情请见我们问题跟踪器上的 Go 1.10.1 里程碑。
go1.10.2(2018-05-01发布)包括对编译器、链接器和go命令的修复。详情请见我们问题追踪器上的Go 1.10.2里程碑。
go1.10.3(2018-06-05发布)包括对go命令以及crypto/tls、crypto/x509和strings包的修复。特别是,它为go命令增加了对vgo过渡的最小支持。详情请见我们问题跟踪器上的 Go 1.10.3 里程碑。
go1.10.4(2018-08-24发布)包括对go命令、链接器以及bytes、mime/multipart、net/http和strings包的修复。详情请见我们问题跟踪器上的Go 1.10.4里程碑。
go1.10.5(2018-11-02发布)包括对go命令、链接器、runtime和database/sql包的修复。详情请见我们问题追踪器上的Go 1.10.5里程碑。
go1.10.6(2018-12-12发布)包括对 “go get“和crypto/x509包的三个安全修正。它包含与Go 1.11.3相同的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.10.6里程碑。
go1.10.7(2018-12-14发布)包含对Go 1.10.6中引入的一个错误的修复,该错误会破坏对包含”...“的导入路径模式的go get。详情请参见问题追踪器上的 Go 1.10.7 里程碑。
go1.10.8(2019-01-23发布)包括一个对crypto/elliptic包的安全修复。详情请见我们问题追踪器上的Go 1.10.8里程碑。
go1.9 (released 2017-08-24)
Go 1.9是Go的一个重要版本。阅读 Go 1.9 发行说明以了解更多信息。
Minor revisions
go1.9.1(2017-10-04发布)包括两个安全修复。请参阅我们的问题跟踪器上的Go 1.9.1里程碑以了解详情。
go1.9.2(2017-10-25发布)包括对编译器、链接器、runtime、文档、go命令以及crypto/x509、database/sql、log和net/smtp包的修正。它包括对 Go 1.9.1 中引入的一个错误的修复,该错误在某些情况下会破坏非 Git 仓库的 go get。详情请参见问题追踪器上的 Go 1.9.2 里程碑。
go1.9.3(2018-01-22发布)包括net/url包的安全修复,以及编译器、runtime、database/sql、math/big和net/http包的错误修复。详情请见我们问题跟踪器上的 Go 1.9.3 里程碑。
go1.9.4(2018-02-07发布)包括一个对 “go get“的安全修复。详见我们问题追踪器上的Go 1.9.4里程碑。
go1.9.5(2018-03-28发布)包括对go命令的安全修复,以及对编译器、go命令和net/http/pprof包的错误修复。详情请见我们问题跟踪器上的Go 1.9.5里程碑。
go1.9.6(2018-05-01发布)包括对编译器和go命令的修复。详情请见我们问题追踪器上的Go 1.9.6里程碑。
go1.9.7(2018-06-05发布)包括对go命令以及crypto/x509和strings包的修复。特别是,它为go命令增加了对vgo过渡的最小支持。详情请见我们问题跟踪器上的Go 1.9.7里程碑。
go1.8 (released 2017-02-16)
Go 1.8是Go的一个重要版本。阅读 Go 1.8 发行说明以了解更多信息。
Minor revisions
go1.8.1(2017-04-07发布)包括对编译器、链接器、runtime、文档、go命令以及crypto/tls、encoding/xml、image/png、net、net/http、reflect、text/template和time包的修复。详情请见我们问题跟踪器上的Go 1.8.1里程碑。
go1.8.2(2017-05-23发布)包括一个对crypto/elliptic包的安全修复。详情请见我们问题追踪器上的Go 1.8.2里程碑。
go1.8.3(2017-05-24发布)包括对编译器、runtime、文档和database/sql包的修复。详情请见我们问题追踪器上的Go 1.8.3里程碑。
go1.8.4(2017-10-04发布)包括两个安全修复。它包含了与Go 1.9.1相同的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.8.4里程碑。
go1.8.5(2017-10-25发布)包括对编译器、链接器、runtime、文档、go命令以及crypto/x509和net/smtp包的修正。它包括对Go 1.8.4中引入的一个错误的修复,该错误在某些条件下破坏了非Git仓库的go get。详情请参见问题跟踪器上的 Go 1.8.5 里程碑。
go1.8.6(2018-01-22发布)包括与Go 1.9.3相同的math/big中的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.8.6里程碑。
go1.8.7(2018-02-07发布)包含一个对 “go get“的安全修复。它包含与Go 1.9.4相同的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.8.7里程碑。
go1.7 (released 2016-08-15)
Go 1.7是Go的一个重要版本。阅读 Go 1.7 发行说明以了解更多信息。
Minor revisions
go1.7.1(2016-09-07发布)包括对编译器、runtime、文档以及compress/flate、hash/crc32、io、net、net/http、path/filepath、reflect和syscall包的修正。详情请见我们问题跟踪器上的 Go 1.7.1 里程碑。
go1.7.2不应被使用。它已被标记但未完全发布。由于最后一分钟的错误报告,该版本被推迟了。请使用go1.7.3来代替,并参考下面的变化摘要。
go1.7.3(2016-10-19发布)包括对编译器、runtime以及crypto/cipher、crypto/tls、net/http和strings包的修复。详情请见我们问题跟踪器上的Go 1.7.3里程碑。
go1.7.4(2016-12-01发布)包括两个安全修复。详见问题追踪器上的 Go 1.7.4 里程碑。
go1.7.5(2017-01-26发布)包括对编译器、runtime以及crypto/x509和time包的修复。详情请见我们的问题跟踪器上的Go 1.7.5里程碑。
go1.7.6(2017-05-23发布)包括与Go 1.8.2相同的安全修复,并在同一时间发布。详情请见我们问题追踪器上的Go 1.8.2里程碑。
go1.6 (released 2016-02-17)
Go 1.6是Go的一个重要版本。阅读 Go 1.6 发行说明以了解更多信息。
Minor revisions
go1.6.1(2016-04-12发布)包括两个安全修复。请参阅我们的问题跟踪器上的 Go 1.6.1 里程碑了解详情。
go1.6.2(2016-04-20发布)包括对编译器、runtime、工具、文档,以及mime/multipart、net/http和sort包的修复。详情请见我们问题跟踪器上的Go 1.6.2里程碑。
go1.6.3(2016-07-17发布)包括在CGI环境下使用net/http/cgi包和net/http包时的安全修复。详情请见我们问题跟踪器上的Go 1.6.3里程碑。
go1.6.4(2016-12-01发布)包括两个安全修复。它包含与Go 1.7.4相同的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.7.4里程碑。
go1.5 (released 2015-08-19)
Go 1.5是Go的一个重要版本。阅读 Go 1.5 发行说明以了解更多信息。
Minor revisions
go1.5.1(2015-09-08发布)包括对编译器、汇编器以及fmt、net/textproto、net/http和runtime包的错误修复。详情请见我们问题跟踪器上的Go 1.5.1里程碑。
go1.5.2(2015-12-02发布)包括对编译器、链接器以及mime/multipart、net和runtime包的错误修复。详情请见我们问题跟踪器上的Go 1.5.2里程碑。
go1.5.3(2016-01-13发布)包括对影响crypto/tls包的math/big包的安全修复。详见发布公告。
go1.5.4(2016-04-12发布)包括两个安全修复。它包含与Go 1.6.1相同的修复,并在同一时间发布。详情请见我们问题跟踪器上的Go 1.6.1里程碑。
go1.4 (released 2014-12-10)
Go 1.4是Go的一个重要版本。阅读 Go 1.4 发行说明以了解更多信息。
Minor revisions
go1.4.1(2015-01-15发布)包括对链接器和log、syscall和runtime包的错误修复。详情请参见我们问题跟踪器上的 Go 1.4.1 里程碑。
go1.4.2(2015-02-17发布)包括对编译器的安全修复,以及对go命令、编译器和链接器以及runtime、syscall、reflect和math/big包的错误修复。详情请见我们问题跟踪器上的 Go 1.4.2 里程碑。
go1.4.3(2015-09-22发布)包括net/http包的安全修复和runtime包的错误修复。详情请见我们问题追踪器上的Go 1.4.3里程碑。
go1.3 (released 2014-06-18)
Go 1.3是Go的一个重要版本。阅读 Go 1.3 发行说明以了解更多信息。
Minor revisions
go1.3.1(2014-08-13发布)包括对编译器以及runtime、net和crypto/rsa包的错误修复。详细内容请参见变更历史。
go1.3.2(2014-09-25发布)包括对crypto/tls包的安全修复和对cgo的错误修复。详见变更历史。
go1.3.3(2014-09-30发布)包括对cgo、runtime 包和nacl端口的进一步错误修复。详见变更历史。
go1.2 (released 2013-12-01)
Go 1.2是Go的一个重要版本。请阅读 Go 1.2 发行说明 以了解更多信息。
Minor revisions
go1.2.1(2014-03-02发布)包括对runtime、net和database/sql包的错误修复。详情请参见变更历史。
go1.2.2(2014-05-05发布)包括一个影响到二进制发行版中包含的tour binary的安全修复(感谢Guillaume T)。
go1.1 (released 2013-05-13)
Go 1.1是Go的一个重要版本。请阅读 Go 1.1 发行说明 以了解更多信息。
Minor revisions
go1.1.1(2013-06-13发布)包括对编译器的安全修复以及对编译器和runtime的若干错误修复。详情请参见变更历史。
go1.1.2(2013-08-13发布)包括对gc编译器和cgo,以及bufio、runtime、syscall和time包的修复。详情请参见变更历史。如果你在ARM或386架构的Linux下使用syscall包的Getrlimit和Setrlimit函数,请注意11803043的变动,它修复了issue 5949。
go1 (released 2012-03-28)
Go 1是Go的一个重要版本,将长期保持稳定。请阅读 Go 1 发行说明了解更多信息。
我们希望为 Go 1 编写的程序能够在未来的 Go 1 版本下继续正确地编译和运行,不做任何改变。 阅读 Go 1 兼容性文件,了解更多关于 Go 1 的未来。
go1版本对应的是weekly.2012-03-27。
Minor revisions
go1.0.1(2012-04-25发布)是为了修复一个可能导致内存损坏的转义分析错误。它还包括几个小的代码和文档修复。
go1.0.2(2012-06-13发布)修正了使用结构体或数组键的映射实现中的两个错误:issue 3695和issue 3573。它还包括许多小的代码和文档修复。
go1.0.3(2012-09-21发布)包括一些小的代码和文档修正。
完整的变化列表请参见go1发布分支历史。
Older releases 较早的版本
请参阅Go1发布前的历史页面,了解早期发布的注意事项。
2 - 标准库
2.1 - archive
2.1.1 - tar
tar
https://pkg.go.dev/archive/tar@go1.20.1
Package tar implements access to tar archives.
Tape archives (tar) are a file format for storing a sequence of files that can be read and written in a streaming manner. This package aims to cover most variations of the format, including those produced by GNU and BSD tar tools.
Example
|
|
常量
|
|
Type flags for Header.Typeflag.
变量
|
|
函数
This section is empty.
类型
type Format <- go1.10
|
|
Format represents the tar archive format.
The original tar format was introduced in Unix V7. Since then, there have been multiple competing formats attempting to standardize or extend the V7 format to overcome its limitations. The most common formats are the USTAR, PAX, and GNU formats, each with their own advantages and limitations.
The following table captures the capabilities of each format:
| USTAR | PAX | GNU
------------------+--------+-----------+----------
Name | 256B | unlimited | unlimited
Linkname | 100B | unlimited | unlimited
Size | uint33 | unlimited | uint89
Mode | uint21 | uint21 | uint57
Uid/Gid | uint21 | unlimited | uint57
Uname/Gname | 32B | unlimited | 32B
ModTime | uint33 | unlimited | int89
AccessTime | n/a | unlimited | int89
ChangeTime | n/a | unlimited | int89
Devmajor/Devminor | uint21 | uint21 | uint57
------------------+--------+-----------+----------
string encoding | ASCII | UTF-8 | binary
sub-second times | no | yes | no
sparse files | no | yes | yes
The table’s upper portion shows the Header fields, where each format reports the maximum number of bytes allowed for each string field and the integer type used to store each numeric field (where timestamps are stored as the number of seconds since the Unix epoch).
The table’s lower portion shows specialized features of each format, such as supported string encodings, support for sub-second timestamps, or support for sparse files.
The Writer currently provides no support for sparse files.
|
|
Constants to identify various tar formats.
(Format) String <- go1.10
|
|
type Header
|
|
A Header represents a single header in a tar archive. Some fields may not be populated.
For forward compatibility, users that retrieve a Header from Reader.Next, mutate it in some ways, and then pass it back to Writer.WriteHeader should do so by creating a new Header and copying the fields that they are interested in preserving.
func FileInfoHeader <- go1.1
|
|
FileInfoHeader creates a partially-populated Header from fi. If fi describes a symlink, FileInfoHeader records link as the link target. If fi describes a directory, a slash is appended to the name.
Since fs.FileInfo’s Name method only returns the base name of the file it describes, it may be necessary to modify Header.Name to provide the full path name of the file.
(*Header) FileInfo <- go1.1
|
|
FileInfo returns an fs.FileInfo for the Header.
type Reader
|
|
Reader provides sequential access to the contents of a tar archive. Reader.Next advances to the next file in the archive (including the first), and then Reader can be treated as an io.Reader to access the file’s data.
func NewReader
|
|
NewReader creates a new Reader reading from r.
(*Reader) Next
|
|
Next advances to the next entry in the tar archive. The Header.Size determines how many bytes can be read for the next file. Any remaining data in the current file is automatically discarded. At the end of the archive, Next returns the error io.EOF.
If Next encounters a non-local name (as defined by filepath.IsLocal) and the GODEBUG environment variable contains tarinsecurepath=0, Next returns the header with an ErrInsecurePath error. A future version of Go may introduce this behavior by default. Programs that want to accept non-local names can ignore the ErrInsecurePath error and use the returned header.
(*Reader) Read
|
|
Read reads from the current file in the tar archive. It returns (0, io.EOF) when it reaches the end of that file, until Next is called to advance to the next file.
If the current file is sparse, then the regions marked as a hole are read back as NUL-bytes.
Calling Read on special types like TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, and TypeFifo returns (0, io.EOF) regardless of what the Header.Size claims.
type Writer
|
|
Writer provides sequential writing of a tar archive. Write.WriteHeader begins a new file with the provided Header, and then Writer can be treated as an io.Writer to supply that file’s data.
func NewWriter
|
|
NewWriter creates a new Writer writing to w.
(*Writer) Close
|
|
Close closes the tar archive by flushing the padding, and writing the footer. If the current file (from a prior call to WriteHeader) is not fully written, then this returns an error.
(*Writer) Flush
|
|
Flush finishes writing the current file’s block padding. The current file must be fully written before Flush can be called.
This is unnecessary as the next call to WriteHeader or Close will implicitly flush out the file’s padding.
(*Writer) Write
|
|
Write writes to the current file in the tar archive. Write returns the error ErrWriteTooLong if more than Header.Size bytes are written after WriteHeader.
Calling Write on special types like TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, and TypeFifo returns (0, ErrWriteTooLong) regardless of what the Header.Size claims.
(*Writer) WriteHeader
|
|
WriteHeader writes hdr and prepares to accept the file’s contents. The Header.Size determines how many bytes can be written for the next file. If the current file is not fully written, then this returns an error. This implicitly flushes any padding necessary before writing the header.
2.1.2 - zip
zip
https://pkg.go.dev/archive/zip@go1.20.1
Package zip provides support for reading and writing ZIP archives.
See the ZIP specification for details.
This package does not support disk spanning.
A note about ZIP64:
To be backwards compatible the FileHeader has both 32 and 64 bit Size fields. The 64 bit fields will always contain the correct value and for normal archives both fields will be the same. For files requiring the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit fields must be used instead.
常量
|
|
Compression methods.
变量
|
|
函数
func RegisterCompressor <- go1.2
|
|
RegisterCompressor registers custom compressors for a specified method ID. The common methods Store and Deflate are built in.
func RegisterDecompressor <- go1.2
|
|
RegisterDecompressor allows custom decompressors for a specified method ID. The common methods Store and Deflate are built in.
类型
type Compressor <- go1.2
|
|
A Compressor returns a new compressing writer, writing to w. The WriteCloser’s Close method must be used to flush pending data to w. The Compressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned writer will be used only by one goroutine at a time.
type Decompressor <- go1.2
|
|
A Decompressor returns a new decompressing reader, reading from r. The ReadCloser’s Close method must be used to release associated resources. The Decompressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned reader will be used only by one goroutine at a time.
type File
|
|
A File is a single file in a ZIP archive. The file information is in the embedded FileHeader. The file content can be accessed by calling Open.
(*File) DataOffset <- go1.2
|
|
DataOffset returns the offset of the file’s possibly-compressed data, relative to the beginning of the zip file.
Most callers should instead use Open, which transparently decompresses data and verifies checksums.
(*File) Open
|
|
Open returns a ReadCloser that provides access to the File’s contents. Multiple files may be read concurrently.
(*File) OpenRaw <- go1.17
|
|
OpenRaw returns a Reader that provides access to the File’s contents without decompression.
type FileHeader
|
|
FileHeader describes a file within a ZIP file. See the ZIP specification for details.
func FileInfoHeader
|
|
FileInfoHeader creates a partially-populated FileHeader from an fs.FileInfo. Because fs.FileInfo’s Name method returns only the base name of the file it describes, it may be necessary to modify the Name field of the returned header to provide the full path name of the file. If compression is desired, callers should set the FileHeader.Method field; it is unset by default.
(*FileHeader) FileInfo
|
|
FileInfo returns an fs.FileInfo for the FileHeader.
Example
|
|
(*FileHeader) Mode
|
|
Mode returns the permission and mode bits for the FileHeader.
Example
|
|
(*FileHeader) SetMode
|
|
SetMode changes the permission and mode bits for the FileHeader.
type ReadCloser
|
|
A ReadCloser is a Reader that must be closed when no longer needed.
func OpenReader
|
|
OpenReader will open the Zip file specified by name and return a ReadCloser.
(*ReadCloser) Close
|
|
Close closes the Zip file, rendering it unusable for I/O.
type Reader
|
|
A Reader serves content from a ZIP archive.
Example
|
|
func NewReader
|
|
NewReader returns a new Reader reading from r, which is assumed to have the given size in bytes.
If any file inside the archive uses a non-local name (as defined by filepath.IsLocal) or a name containing backslashes and the GODEBUG environment variable contains zipinsecurepath=0, NewReader returns the reader with an ErrInsecurePath error. A future version of Go may introduce this behavior by default. Programs that want to accept non-local names can ignore the ErrInsecurePath error and use the returned reader.
(*Reader) Open <- go1.16
|
|
Open opens the named file in the ZIP archive, using the semantics of fs.FS.Open: paths are always slash separated, with no leading / or ../ elements.
(*Reader) RegisterDecompressor <- go1.6
|
|
RegisterDecompressor registers or overrides a custom decompressor for a specific method ID. If a decompressor for a given method is not found, Reader will default to looking up the decompressor at the package level.
type Writer
|
|
Writer implements a zip file writer.
Example
|
|
func NewWriter
|
|
NewWriter returns a new Writer writing a zip file to w.
(*Writer) Close
|
|
Close finishes writing the zip file by writing the central directory. It does not close the underlying writer.
(*Writer) Copy <- go1.17
|
|
Copy copies the file f (obtained from a Reader) into w. It copies the raw form directly bypassing decompression, compression, and validation.
(*Writer) Create
|
|
Create adds a file to the zip file using the provided name. It returns a Writer to which the file contents should be written. The file contents will be compressed using the Deflate method. The name must be a relative path: it must not start with a drive letter (e.g. C:) or leading slash, and only forward slashes are allowed. To create a directory instead of a file, add a trailing slash to the name. The file’s contents must be written to the io.Writer before the next call to Create, CreateHeader, or Close.
(*Writer) CreateHeader
|
|
CreateHeader adds a file to the zip archive using the provided FileHeader for the file metadata. Writer takes ownership of fh and may mutate its fields. The caller must not modify fh after calling CreateHeader.
This returns a Writer to which the file contents should be written. The file’s contents must be written to the io.Writer before the next call to Create, CreateHeader, CreateRaw, or Close.
(*Writer) CreateRaw <- go1.17
|
|
CreateRaw adds a file to the zip archive using the provided FileHeader and returns a Writer to which the file contents should be written. The file’s contents must be written to the io.Writer before the next call to Create, CreateHeader, CreateRaw, or Close.
In contrast to CreateHeader, the bytes passed to Writer are not compressed.
(*Writer) Flush <- go1.4
|
|
Flush flushes any buffered data to the underlying writer. Calling Flush is not normally necessary; calling Close is sufficient.
(*Writer) RegisterCompressor <- go1.6
|
|
RegisterCompressor registers or overrides a custom compressor for a specific method ID. If a compressor for a given method is not found, Writer will default to looking up the compressor at the package level.
Example
|
|
(*Writer) SetComment <- go1.10
|
|
SetComment sets the end-of-central-directory comment field. It can only be called before Close.
(*Writer) SetOffset <- go1.5
|
|
SetOffset sets the offset of the beginning of the zip data within the underlying writer. It should be used when the zip data is appended to an existing file, such as a binary executable. It must be called before any data is written.
2.2 - compress
2.2.1 - bzip2
bzip2
https://pkg.go.dev/compress/bzip2@go1.20.1
Package bzip2 implements bzip2 decompression.
常量
This section is empty.
变量
This section is empty.
函数
func NewReader
|
|
NewReader returns an io.Reader which decompresses bzip2 data from r. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r.
类型
type StructuralError
|
|
A StructuralError is returned when the bzip2 data is found to be syntactically invalid.
(StructuralError) Error
|
|
2.2.2 - flate
flate
https://pkg.go.dev/compress/flate@go1.20.1
Package flate implements the DEFLATE compressed data format, described in RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file formats.
Example
|
|
Example
|
|
Example
|
|
常量
|
|
变量
This section is empty.
函数
func NewReader
|
|
NewReader returns a new ReadCloser that can be used to read the uncompressed version of r. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r. The reader returns io.EOF after the final block in the DEFLATE stream has been encountered. Any trailing data after the final block is ignored.
The ReadCloser returned by NewReader also implements Resetter.
func NewReaderDict
|
|
NewReaderDict is like NewReader but initializes the reader with a preset dictionary. The returned Reader behaves as if the uncompressed data stream started with the given dictionary, which has already been read. NewReaderDict is typically used to read data compressed by NewWriterDict.
The ReadCloser returned by NewReader also implements Resetter.
类型
type CorruptInputError
|
|
A CorruptInputError reports the presence of corrupt input at a given offset.
(CorruptInputError) Error
|
|
type InternalError
|
|
An InternalError reports an error in the flate code itself.
(InternalError) Error
|
|
Example
|
|
type Reader
|
|
The actual read interface needed by NewReader. If the passed in io.Reader does not also have ReadByte, the NewReader will introduce its own buffering.
type Resetter <- go1.4
|
|
Resetter resets a ReadCloser returned by NewReader or NewReaderDict to switch to a new underlying Reader. This permits reusing a ReadCloser instead of allocating a new one.
Example
|
|
type Writer
|
|
A Writer takes data written to it and writes the compressed form of that data to an underlying writer (see NewWriter).
func NewWriter
|
|
NewWriter returns a new Writer compressing data at the given level. Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression); higher levels typically run slower but compress more. Level 0 (NoCompression) does not attempt any compression; it only adds the necessary DEFLATE framing. Level -1 (DefaultCompression) uses the default compression level. Level -2 (HuffmanOnly) will use Huffman compression only, giving a very fast compression for all types of input, but sacrificing considerable compression efficiency.
If level is in the range [-2, 9] then the error returned will be nil. Otherwise the error returned will be non-nil.
func NewWriterDict
|
|
NewWriterDict is like NewWriter but initializes the new Writer with a preset dictionary. The returned Writer behaves as if the dictionary had been written to it without producing any compressed output. The compressed data written to w can only be decompressed by a Reader initialized with the same dictionary.
(*Writer) Close
|
|
Close flushes and closes the writer.
(*Writer) Flush
|
|
Flush flushes any pending data to the underlying writer. It is useful mainly in compressed network protocols, to ensure that a remote reader has enough data to reconstruct a packet. Flush does not return until the data has been written. Calling Flush when there is no pending data still causes the Writer to emit a sync marker of at least 4 bytes. If the underlying writer returns an error, Flush returns that error.
In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
(*Writer) Reset <- go1.2
|
|
Reset discards the writer’s state and makes it equivalent to the result of NewWriter or NewWriterDict called with dst and w’s level and dictionary.
(*Writer) Write
|
|
Write writes data to w, which will eventually write the compressed form of data to its underlying writer.
2.2.3 - gzip
gzip
https://pkg.go.dev/compress/gzip@go1.20.1
Package gzip implements reading and writing of gzip format compressed files, as specified in RFC 1952.
Example
|
|
Example
|
|
常量
|
|
These constants are copied from the flate package, so that code that imports “compress/gzip” does not also have to import “compress/flate”.
变量
|
|
函数
This section is empty.
类型
type Header
|
|
The gzip file stores a header giving metadata about the compressed file. That header is exposed as the fields of the Writer and Reader structs.
Strings must be UTF-8 encoded and may only contain Unicode code points U+0001 through U+00FF, due to limitations of the GZIP file format.
type Reader
|
|
A Reader is an io.Reader that can be read to retrieve uncompressed data from a gzip-format compressed file.
In general, a gzip file can be a concatenation of gzip files, each with its own header. Reads from the Reader return the concatenation of the uncompressed data of each. Only the first header is recorded in the Reader fields.
Gzip files store a length and checksum of the uncompressed data. The Reader will return an ErrChecksum when Read reaches the end of the uncompressed data if it does not have the expected length or checksum. Clients should treat data returned by Read as tentative until they receive the io.EOF marking the end of the data.
func NewReader
|
|
NewReader creates a new Reader reading the given reader. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r.
It is the caller’s responsibility to call Close on the Reader when done.
The Reader.Header fields will be valid in the Reader returned.
(*Reader) Close
|
|
Close closes the Reader. It does not close the underlying io.Reader. In order for the GZIP checksum to be verified, the reader must be fully consumed until the io.EOF.
(*Reader) Multistream <- go1.4
|
|
Multistream controls whether the reader supports multistream files.
If enabled (the default), the Reader expects the input to be a sequence of individually gzipped data streams, each with its own header and trailer, ending at EOF. The effect is that the concatenation of a sequence of gzipped files is treated as equivalent to the gzip of the concatenation of the sequence. This is standard behavior for gzip readers.
Calling Multistream(false) disables this behavior; disabling the behavior can be useful when reading file formats that distinguish individual gzip data streams or mix gzip data streams with other data streams. In this mode, when the Reader reaches the end of the data stream, Read returns io.EOF. The underlying reader must implement io.ByteReader in order to be left positioned just after the gzip stream. To start the next stream, call z.Reset(r) followed by z.Multistream(false). If there is no next stream, z.Reset(r) will return io.EOF.
Example
|
|
(*Reader) Read
|
|
Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
(*Reader) Reset <- go1.3
|
|
Reset discards the Reader z’s state and makes it equivalent to the result of its original state from NewReader, but reading from r instead. This permits reusing a Reader rather than allocating a new one.
type Writer
|
|
A Writer is an io.WriteCloser. Writes to a Writer are compressed and written to w.
func NewWriter
|
|
NewWriter returns a new Writer. Writes to the returned writer are compressed and written to w.
It is the caller’s responsibility to call Close on the Writer when done. Writes may be buffered and not flushed until Close.
Callers that wish to set the fields in Writer.Header must do so before the first call to Write, Flush, or Close.
func NewWriterLevel
|
|
NewWriterLevel is like NewWriter but specifies the compression level instead of assuming DefaultCompression.
The compression level can be DefaultCompression, NoCompression, HuffmanOnly or any integer value between BestSpeed and BestCompression inclusive. The error returned will be nil if the level is valid.
(*Writer) Close
|
|
Close closes the Writer by flushing any unwritten data to the underlying io.Writer and writing the GZIP footer. It does not close the underlying io.Writer.
(*Writer) Flush <- go1.1
|
|
Flush flushes any pending compressed data to the underlying writer.
It is useful mainly in compressed network protocols, to ensure that a remote reader has enough data to reconstruct a packet. Flush does not return until the data has been written. If the underlying writer returns an error, Flush returns that error.
In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
(*Writer) Reset <- go1.2
|
|
Reset discards the Writer z’s state and makes it equivalent to the result of its original state from NewWriter or NewWriterLevel, but writing to w instead. This permits reusing a Writer rather than allocating a new one.
(*Writer) Write
|
|
Write writes a compressed form of p to the underlying io.Writer. The compressed bytes are not necessarily flushed until the Writer is closed.
2.2.4 - lzw
lzw
https://pkg.go.dev/compress/lzw@go1.20.1
Package lzw implements the Lempel-Ziv-Welch compressed data format, described in T. A. Welch, “A Technique for High-Performance Data Compression”, Computer, 17(6) (June 1984), pp 8-19.
In particular, it implements LZW as used by the GIF and PDF file formats, which means variable-width codes up to 12 bits and the first two non-literal codes are a clear code and an EOF code.
The TIFF file format uses a similar but incompatible version of the LZW algorithm. See the golang.org/x/image/tiff/lzw package for an implementation.
常量
This section is empty.
变量
This section is empty.
函数
func NewReader
|
|
NewReader creates a new io.ReadCloser. Reads from the returned io.ReadCloser read and decompress data from r. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r. It is the caller’s responsibility to call Close on the ReadCloser when finished reading. The number of bits to use for literal codes, litWidth, must be in the range [2,8] and is typically 8. It must equal the litWidth used during compression.
It is guaranteed that the underlying type of the returned io.ReadCloser is a *Reader.
func NewWriter
|
|
NewWriter creates a new io.WriteCloser. Writes to the returned io.WriteCloser are compressed and written to w. It is the caller’s responsibility to call Close on the WriteCloser when finished writing. The number of bits to use for literal codes, litWidth, must be in the range [2,8] and is typically 8. Input bytes must be less than 1«litWidth.
It is guaranteed that the underlying type of the returned io.WriteCloser is a *Writer.
类型
type Order
|
|
Order specifies the bit ordering in an LZW data stream.
|
|
type Reader <- go1.17
|
|
Reader is an io.Reader which can be used to read compressed data in the LZW format.
(*Reader) Close <- go1.17
|
|
Close closes the Reader and returns an error for any future read operation. It does not close the underlying io.Reader.
(*Reader) Read <- go1.17
|
|
Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
(*Reader) Reset <- go1.17
|
|
Reset clears the Reader’s state and allows it to be reused again as a new Reader.
type Writer <- go1.17
|
|
Writer is an LZW compressor. It writes the compressed form of the data to an underlying writer (see NewWriter).
(*Writer) Close <- go1.17
|
|
Close closes the Writer, flushing any pending output. It does not close w’s underlying writer.
(*Writer) Reset <- go1.17
|
|
Reset clears the Writer’s state and allows it to be reused again as a new Writer.
(*Writer) Write <- go1.17
|
|
Write writes a compressed representation of p to w’s underlying writer.
2.2.5 - zlib
zlib
https://pkg.go.dev/compress/zlib@go1.20.1
Package zlib implements reading and writing of zlib format compressed data, as specified in RFC 1950.
The implementation provides filters that uncompress during reading and compress during writing. For example, to write compressed data to a buffer:
|
|
and to read that data back:
r, err := zlib.NewReader(&b)
io.Copy(os.Stdout, r)
r.Close()
常量
|
|
These constants are copied from the flate package, so that code that imports “compress/zlib” does not also have to import “compress/flate”.
变量
|
|
函数
func NewReader
|
|
NewReader creates a new ReadCloser. Reads from the returned ReadCloser read and decompress data from r. If r does not implement io.ByteReader, the decompressor may read more data than necessary from r. It is the caller’s responsibility to call Close on the ReadCloser when done.
The ReadCloser returned by NewReader also implements Resetter.
Example
|
|
func NewReaderDict
|
|
NewReaderDict is like NewReader but uses a preset dictionary. NewReaderDict ignores the dictionary if the compressed data does not refer to it. If the compressed data refers to a different dictionary, NewReaderDict returns ErrDictionary.
The ReadCloser returned by NewReaderDict also implements Resetter.
类型
type Resetter <- go1.4
|
|
Resetter resets a ReadCloser returned by NewReader or NewReaderDict to switch to a new underlying Reader. This permits reusing a ReadCloser instead of allocating a new one.
type Writer
|
|
A Writer takes data written to it and writes the compressed form of that data to an underlying writer (see NewWriter).
func NewWriter
|
|
NewWriter creates a new Writer. Writes to the returned Writer are compressed and written to w.
It is the caller’s responsibility to call Close on the Writer when done. Writes may be buffered and not flushed until Close.
Example
|
|
func NewWriterLevel
|
|
NewWriterLevel is like NewWriter but specifies the compression level instead of assuming DefaultCompression.
The compression level can be DefaultCompression, NoCompression, HuffmanOnly or any integer value between BestSpeed and BestCompression inclusive. The error returned will be nil if the level is valid.
func NewWriterLevelDict
|
|
NewWriterLevelDict is like NewWriterLevel but specifies a dictionary to compress with.
The dictionary may be nil. If not, its contents should not be modified until the Writer is closed.
(*Writer) Close
|
|
Close closes the Writer, flushing any unwritten data to the underlying io.Writer, but does not close the underlying io.Writer.
(*Writer) Flush
|
|
Flush flushes the Writer to its underlying io.Writer.
(*Writer) Reset <- go1.2
|
|
Reset clears the state of the Writer z such that it is equivalent to its initial state from NewWriterLevel or NewWriterLevelDict, but instead writing to w.
(*Writer) Write
|
|
Write writes a compressed form of p to the underlying io.Writer. The compressed bytes are not necessarily flushed until the Writer is closed or explicitly flushed.
2.3 - container
2.3.1 - heap
heap
https://pkg.go.dev/container/heap@go1.20.1
Package heap provides heap operations for any type that implements heap.Interface. A heap is a tree with the property that each node is the minimum-valued node in its subtree.
包heap为任何实现heap.Interface的类型提供堆操作。堆是一棵树,其属性是每个节点都是其子树中的最小值节点。
The minimum element in the tree is the root, at index 0.
树中的最小元素是根,索引为0。
A heap is a common way to implement a priority queue. To build a priority queue, implement the Heap interface with the (negative) priority as the ordering for the Less method, so Push adds items while Pop removes the highest-priority item from the queue. The Examples include such an implementation; the file example_pq_test.go has the complete source.
heap 是实现优先级队列的一种常见方式。要建立一个优先级队列,要用(负)优先级作为Less方法的排序来实现Heap接口,因此Push增加项目,而Pop从队列中删除优先级最高的项目。实例中包括这样的实现;文件example_pq_test.go中有完整的源代码。
Example
|
|
Example
|
|
常量
This section is empty.
变量
This section is empty.
函数
func Fix <- go1.2
|
|
Fix re-establishes the heap ordering after the element at index i has changed its value. Changing the value of the element at index i and then calling Fix is equivalent to, but less expensive than, calling Remove(h, i) followed by a Push of the new value. The complexity is O(log n) where n = h.Len().
Fix在索引i处的元素改变其值后重新建立堆的顺序。改变索引i处元素的值,然后调用Fix,相当于调用Remove(h, i),然后推送新的值,但成本较低。复杂度是O(log n),其中n = h.Len()。
func Init
|
|
Init establishes the heap invariants required by the other routines in this package. Init is idempotent with respect to the heap invariants and may be called whenever the heap invariants may have been invalidated. The complexity is O(n) where n = h.Len().
Init建立了本包中其他例程所要求的堆不变性。Init对于堆不变性来说是等价的,只要堆不变性可能已经失效,就可以调用它。复杂度为O(n),其中n = h.Len()。
func Pop
|
|
Pop removes and returns the minimum element (according to Less) from the heap. The complexity is O(log n) where n = h.Len(). Pop is equivalent to Remove(h, 0).
Pop删除并返回堆中的最小元素(根据Less)。复杂度为O(log n),其中n = h.Len()。Pop等同于Remove(h, 0)。
func Push
|
|
Push pushes the element x onto the heap. The complexity is O(log n) where n = h.Len().
Push将元素x推到堆上。复杂度为O(log n),其中n = h.Len()。
func Remove
|
|
Remove removes and returns the element at index i from the heap. The complexity is O(log n) where n = h.Len().
Remove从堆中删除并返回索引为i的元素。复杂度为O(log n),其中n = h.Len()。
类型
type Interface
|
|
The Interface type describes the requirements for a type using the routines in this package. Any type that implements it may be used as a min-heap with the following invariants (established after Init has been called or if the data is empty or sorted):
接口类型描述了一个使用本包中的例程的类型的要求。任何实现它的类型都可以作为最小堆使用,并具有以下不变性(在调用Init后或数据为空或被排序后建立):
!h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len()
Note that Push and Pop in this interface are for package heap’s implementation to call. To add and remove things from the heap, use heap.Push and heap.Pop.
注意,这个接口中的Push和Pop是供包堆的实现调用的。要从堆中添加和删除东西,请使用heap.Push和heap.Pop。
2.3.2 - list
list
https://pkg.go.dev/container/list@go1.20.1
Package list implements a doubly linked list.
包list实现了一个双链表。
To iterate over a list (where l is a *List):
要在一个列表上进行迭代(其中l是一个*List):
for e := l.Front(); e != nil; e = e.Next() {
// do something with e.Value
//对e.Value做一些处理
}
Example
|
|
常量
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type Element
|
|
Element is an element of a linked list.
Element是链接列表的一个元素。
(*Element) Next
|
|
Next returns the next list element or nil.
Next 返回下一个列表元素或nil。
(*Element) Prev
|
|
Prev returns the previous list element or nil.
Prev返回前一个列表元素或nil。
type List
|
|
List represents a doubly linked list. The zero value for List is an empty list ready to use.
List表示一个双链表。List的零值是一个准备使用的空列表。
func New
|
|
New returns an initialized list.
New返回一个初始化的列表。
(*List) Back
|
|
Back returns the last element of list l or nil if the list is empty.
Back返回列表l的最后一个元素,如果列表为空,则返回nil。
(*List) Front
|
|
Front returns the first element of list l or nil if the list is empty.
Front返回列表l的第一个元素,如果列表为空则返回nil。
(*List) Init
|
|
Init initializes or clears list l.
Init 初始化或清除列表l。
(*List) InsertAfter
|
|
InsertAfter inserts a new element e with value v immediately after mark and returns e. If mark is not an element of l, the list is not modified. The mark must not be nil.
InsertAfter在mark之后插入一个新的元素e,其值为v,并返回e。如果mark不是l的一个元素,列表不会被修改。mark不能是nil。
(*List) InsertBefore
|
|
InsertBefore inserts a new element e with value v immediately before mark and returns e. If mark is not an element of l, the list is not modified. The mark must not be nil.
InsertBefore在mark之前插入一个新的元素e,其值为v,并返回e,如果mark不是l的一个元素,列表就不会被修改。mark不能是nil。
(*List) Len
|
|
Len returns the number of elements of list l. The complexity is O(1).
Len返回列表l的元素数,其复杂度为O(1)。
(*List) MoveAfter <- go1.2
|
|
MoveAfter moves element e to its new position after mark. If e or mark is not an element of l, or e == mark, the list is not modified. The element and mark must not be nil.
MoveAfter将元素e移动到mark之后的新位置。如果e或mark不是l的一个元素,或者e == mark,列表不会被修改。元素和mark不能是nil。
(*List) MoveBefore <- go1.2
|
|
MoveBefore moves element e to its new position before mark. If e or mark is not an element of l, or e == mark, the list is not modified. The element and mark must not be nil.
MoveBefore将元素e移动到mark之前的新位置。如果e或mark不是l的一个元素,或者e == mark,列表不会被修改。元素和mark不能是nil。
(*List) MoveToBack
|
|
MoveToBack moves element e to the back of list l. If e is not an element of l, the list is not modified. The element must not be nil.
MoveToBack把元素e移到列表l的后面。如果e不是l的一个元素,列表不会被修改。该元素不能是nil。
(*List) MoveToFront
|
|
MoveToFront moves element e to the front of list l. If e is not an element of l, the list is not modified. The element must not be nil.
MoveToFront把元素e移到列表l的前面,如果e不是l的元素,列表不被修改。该元素不能是nil。
(*List) PushBack
|
|
PushBack inserts a new element e with value v at the back of list l and returns e.
PushBack在列表l的后面插入一个新元素e,其值为v,并返回e。
(*List) PushBackList
|
|
PushBackList inserts a copy of another list at the back of list l. The lists l and other may be the same. They must not be nil.
PushBackList在列表l的后面插入一个另一个列表的副本。它们不能是nil。
(*List) PushFront
|
|
PushFront inserts a new element e with value v at the front of list l and returns e.
PushFront在列表l的前面插入一个值为v的新元素e,并返回e。
(*List) PushFrontList
|
|
PushFrontList inserts a copy of another list at the front of list l. The lists l and other may be the same. They must not be nil.
PushFrontList在列表l的前面插入一个另一个列表的副本。它们不能是nil。
(*List) Remove
|
|
Remove removes e from l if e is an element of list l. It returns the element value e.Value. The element must not be nil.
如果e是列表l的一个元素,Remove将e从l中移除,并返回元素值e.Value。该元素不能是nil。
2.3.3 - ring
ring
https://pkg.go.dev/container/ring@go1.20.1
Package ring implements operations on circular lists.
ring 包实现了对循环列表的操作。
常量
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type Ring
|
|
A Ring is an element of a circular list, or ring. Rings do not have a beginning or end; a pointer to any ring element serves as reference to the entire ring. Empty rings are represented as nil Ring pointers. The zero value for a Ring is a one-element ring with a nil Value.
Ring是一个循环列表的一个元素,或者说是环。环没有开始或结束;任何环元素的指针都可以作为整个环的参考。空的环表示为nil Ring指针。一个环的零值是一个具有nil值的单元素环。
func New
|
|
New creates a ring of n elements.
New创建一个有n个元素的环。
(*Ring) Do
|
|
Do calls function f on each element of the ring, in forward order. The behavior of Do is undefined if f changes *r.
Do在环的每个元素上以正向顺序调用函数f。如果f改变了*r,Do的行为是未定义的。
Example
|
|
(*Ring) Len
|
|
Len computes the number of elements in ring r. It executes in time proportional to the number of elements.
Len计算环中元素的数量,执行时间与元素的数量成正比。
Example
|
|
(*Ring) Link
|
|
Link connects ring r with ring s such that r.Next() becomes s and returns the original value for r.Next(). r must not be empty.
Link将r环和s环连接起来,这样r.Next()就变成了s,并返回r.Next()的原始值,r不能为空。
If r and s point to the same ring, linking them removes the elements between r and s from the ring. The removed elements form a subring and the result is a reference to that subring (if no elements were removed, the result is still the original value for r.Next(), and not nil).
如果r和s指向同一个环,连接它们会从环中移除r和s之间的元素。被移除的元素形成一个子环,结果是对该子环的引用(如果没有元素被移除,结果仍然是r.Next()的原始值,而不是nil)。
If r and s point to different rings, linking them creates a single ring with the elements of s inserted after r. The result points to the element following the last element of s after insertion.
如果r和s指向不同的环,连接它们会创建一个单一的环,其中s的元素插入到r之后。
Example
|
|
(*Ring) Move
|
|
Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) in the ring and returns that ring element. r must not be empty.
Move在环中向后(n < 0)或向前(n >= 0)移动n % r.Len()元素,并返回该环元素。
Example
|
|
(*Ring) Next
|
|
Next returns the next ring element. r must not be empty.
Next 返回下一个环状元素,r必须不是空的。
Example
|
|
(*Ring) Prev
|
|
Prev returns the previous ring element. r must not be empty.
Prev返回上一个环状元素,r不能为空。
Example
|
|
(*Ring) Unlink
|
|
Unlink removes n % r.Len() elements from the ring r, starting at r.Next(). If n % r.Len() == 0, r remains unchanged. The result is the removed subring. r must not be empty.
Unlink从r环中移除n % r.Len()元素,从r.Next()开始。如果n % r.Len() == 0,r保持不变。结果是移除的子环。
|
|
2.4 - crypto
2.4.1 - aes
aes
https://pkg.go.dev/crypto/aes@go1.20.1
Package aes implements AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197.
The AES operations in this package are not implemented using constant-time algorithms. An exception is when running on systems with enabled hardware support for AES that makes these operations constant-time. Examples include amd64 systems using AES-NI extensions and s390x systems using Message-Security-Assist extensions. On such systems, when the result of NewCipher is passed to cipher.NewGCM, the GHASH operation used by GCM is also constant-time.
常量 ¶
const BlockSize = 16
The AES block size in bytes.
变量
This section is empty.
函数
func NewCipher ¶
func NewCipher(key []byte) (cipher.Block, error)
NewCipher creates and returns a new cipher.Block. The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
类型
type KeySizeError ¶
type KeySizeError int
(KeySizeError) Error ¶
func (k KeySizeError) Error() string
2.4.2 - cipher
cipher
https://pkg.go.dev/crypto/cipher@go1.20.1
Package cipher implements standard block cipher modes that can be wrapped around low-level block cipher implementations. See https://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html and NIST Special Publication 800-38A.
常量 ¶
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type AEAD ¶added in go1.2
type AEAD interface {
// NonceSize returns the size of the nonce that must be passed to Seal
// and Open.
NonceSize() int
// Overhead returns the maximum difference between the lengths of a
// plaintext and its ciphertext.
Overhead() int
// Seal encrypts and authenticates plaintext, authenticates the
// additional data and appends the result to dst, returning the updated
// slice. The nonce must be NonceSize() bytes long and unique for all
// time, for a given key.
//
// To reuse plaintext's storage for the encrypted output, use plaintext[:0]
// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
Seal(dst, nonce, plaintext, additionalData []byte) []byte
// Open decrypts and authenticates ciphertext, authenticates the
// additional data and, if successful, appends the resulting plaintext
// to dst, returning the updated slice. The nonce must be NonceSize()
// bytes long and both it and the additional data must match the
// value passed to Seal.
//
// To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
//
// Even if the function fails, the contents of dst, up to its capacity,
// may be overwritten.
Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
}
AEAD is a cipher mode providing authenticated encryption with associated data. For a description of the methodology, see https://en.wikipedia.org/wiki/Authenticated_encryption.
func NewGCM ¶added in go1.2
func NewGCM(cipher Block) (AEAD, error)
NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode with the standard nonce length.
In general, the GHASH operation performed by this implementation of GCM is not constant-time. An exception is when the underlying Block was created by aes.NewCipher on systems with hardware support for AES. See the crypto/aes package documentation for details.
func NewGCMWithNonceSize ¶added in go1.5
func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error)
NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois Counter Mode, which accepts nonces of the given length. The length must not be zero.
Only use this function if you require compatibility with an existing cryptosystem that uses non-standard nonce lengths. All other users should use NewGCM, which is faster and more resistant to misuse.
func NewGCMWithTagSize ¶added in go1.11
func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error)
NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois Counter Mode, which generates tags with the given length.
Tag sizes between 12 and 16 bytes are allowed.
Only use this function if you require compatibility with an existing cryptosystem that uses non-standard tag lengths. All other users should use NewGCM, which is more resistant to misuse.
type Block ¶
type Block interface {
// BlockSize returns the cipher's block size.
BlockSize() int
// Encrypt encrypts the first block in src into dst.
// Dst and src must overlap entirely or not at all.
Encrypt(dst, src []byte)
// Decrypt decrypts the first block in src into dst.
// Dst and src must overlap entirely or not at all.
Decrypt(dst, src []byte)
}
A Block represents an implementation of block cipher using a given key. It provides the capability to encrypt or decrypt individual blocks. The mode implementations extend that capability to streams of blocks.
type BlockMode ¶
type BlockMode interface {
// BlockSize returns the mode's block size.
BlockSize() int
// CryptBlocks encrypts or decrypts a number of blocks. The length of
// src must be a multiple of the block size. Dst and src must overlap
// entirely or not at all.
//
// If len(dst) < len(src), CryptBlocks should panic. It is acceptable
// to pass a dst bigger than src, and in that case, CryptBlocks will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to CryptBlocks behave as if the concatenation of
// the src buffers was passed in a single run. That is, BlockMode
// maintains state and does not reset at each CryptBlocks call.
CryptBlocks(dst, src []byte)
}
A BlockMode represents a block cipher running in a block-based mode (CBC, ECB etc).
func NewCBCDecrypter ¶
func NewCBCDecrypter(b Block, iv []byte) BlockMode
NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining mode, using the given Block. The length of iv must be the same as the Block’s block size and must match the iv used to encrypt the data.
func NewCBCEncrypter ¶
func NewCBCEncrypter(b Block, iv []byte) BlockMode
NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining mode, using the given Block. The length of iv must be the same as the Block’s block size.
type Stream ¶
type Stream interface {
// XORKeyStream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
// If len(dst) < len(src), XORKeyStream should panic. It is acceptable
// to pass a dst bigger than src, and in that case, XORKeyStream will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to XORKeyStream behave as if the concatenation of
// the src buffers was passed in a single run. That is, Stream
// maintains state and does not reset at each XORKeyStream call.
XORKeyStream(dst, src []byte)
}
A Stream represents a stream cipher.
func NewCFBDecrypter ¶
func NewCFBDecrypter(block Block, iv []byte) Stream
NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode, using the given Block. The iv must be the same length as the Block’s block size.
func NewCFBEncrypter ¶
func NewCFBEncrypter(block Block, iv []byte) Stream
NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode, using the given Block. The iv must be the same length as the Block’s block size.
func NewCTR ¶
func NewCTR(block Block, iv []byte) Stream
NewCTR returns a Stream which encrypts/decrypts using the given Block in counter mode. The length of iv must be the same as the Block’s block size.
func NewOFB ¶
func NewOFB(b Block, iv []byte) Stream
NewOFB returns a Stream that encrypts or decrypts using the block cipher b in output feedback mode. The initialization vector iv’s length must be equal to b’s block size.
type StreamReader ¶
type StreamReader struct {
S Stream
R io.Reader
}
StreamReader wraps a Stream into an io.Reader. It calls XORKeyStream to process each slice of data which passes through.
(StreamReader) Read ¶
func (r StreamReader) Read(dst []byte) (n int, err error)
type StreamWriter ¶
type StreamWriter struct {
S Stream
W io.Writer
Err error // unused
}
StreamWriter wraps a Stream into an io.Writer. It calls XORKeyStream to process each slice of data which passes through. If any Write call returns short then the StreamWriter is out of sync and must be discarded. A StreamWriter has no internal buffering; Close does not need to be called to flush write data.
(StreamWriter) Close ¶
func (w StreamWriter) Close() error
Close closes the underlying Writer and returns its Close return value, if the Writer is also an io.Closer. Otherwise it returns nil.
(StreamWriter) Write ¶
func (w StreamWriter) Write(src []byte) (n int, err error)
2.4.3 - crypto
crypto
https://pkg.go.dev/crypto@go1.20.1
Package crypto collects common cryptographic constants.
常量 ¶
This section is empty.
变量
This section is empty.
函数
func RegisterHash ¶
func RegisterHash(h Hash, f func() hash.Hash)
RegisterHash registers a function that returns a new instance of the given hash function. This is intended to be called from the init function in packages that implement hash functions.
类型
type Decrypter ¶added in go1.5
type Decrypter interface {
// Public returns the public key corresponding to the opaque,
// private key.
Public() PublicKey
// Decrypt decrypts msg. The opts argument should be appropriate for
// the primitive used. See the documentation in each implementation for
// details.
Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)
}
Decrypter is an interface for an opaque private key that can be used for asymmetric decryption operations. An example would be an RSA key kept in a hardware module.
type DecrypterOpts ¶added in go1.5
type DecrypterOpts any
type Hash ¶
type Hash uint
Hash identifies a cryptographic hash function that is implemented in another package.
const (
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
MD5 // import crypto/md5
SHA1 // import crypto/sha1
SHA224 // import crypto/sha256
SHA256 // import crypto/sha256
SHA384 // import crypto/sha512
SHA512 // import crypto/sha512
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
RIPEMD160 // import golang.org/x/crypto/ripemd160
SHA3_224 // import golang.org/x/crypto/sha3
SHA3_256 // import golang.org/x/crypto/sha3
SHA3_384 // import golang.org/x/crypto/sha3
SHA3_512 // import golang.org/x/crypto/sha3
SHA512_224 // import crypto/sha512
SHA512_256 // import crypto/sha512
BLAKE2s_256 // import golang.org/x/crypto/blake2s
BLAKE2b_256 // import golang.org/x/crypto/blake2b
BLAKE2b_384 // import golang.org/x/crypto/blake2b
BLAKE2b_512 // import golang.org/x/crypto/blake2b
)
(Hash) Available ¶
func (h Hash) Available() bool
Available reports whether the given hash function is linked into the binary.
(Hash) HashFunc ¶added in go1.4
func (h Hash) HashFunc() Hash
HashFunc simply returns the value of h so that Hash implements SignerOpts.
(Hash) New ¶
func (h Hash) New() hash.Hash
New returns a new hash.Hash calculating the given hash function. New panics if the hash function is not linked into the binary.
(Hash) Size ¶
func (h Hash) Size() int
Size returns the length, in bytes, of a digest resulting from the given hash function. It doesn’t require that the hash function in question be linked into the program.
(Hash) String ¶added in go1.15
func (h Hash) String() string
type PrivateKey ¶
type PrivateKey any
PrivateKey represents a private key using an unspecified algorithm.
Although this type is an empty interface for backwards compatibility reasons, all private key types in the standard library implement the following interface
interface{
Public() crypto.PublicKey
Equal(x crypto.PrivateKey) bool
}
as well as purpose-specific interfaces such as Signer and Decrypter, which can be used for increased type safety within applications.
type PublicKey ¶added in go1.2
type PublicKey any
PublicKey represents a public key using an unspecified algorithm.
Although this type is an empty interface for backwards compatibility reasons, all public key types in the standard library implement the following interface
interface{
Equal(x crypto.PublicKey) bool
}
which can be used for increased type safety within applications.
type Signer ¶added in go1.4
type Signer interface {
// Public returns the public key corresponding to the opaque,
// private key.
Public() PublicKey
// Sign signs digest with the private key, possibly using entropy from
// rand. For an RSA key, the resulting signature should be either a
// PKCS #1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA
// key, it should be a DER-serialised, ASN.1 signature structure.
//
// Hash implements the SignerOpts interface and, in most cases, one can
// simply pass in the hash function used as opts. Sign may also attempt
// to type assert opts to other types in order to obtain algorithm
// specific values. See the documentation in each package for details.
//
// Note that when a signature of a hash of a larger message is needed,
// the caller is responsible for hashing the larger message and passing
// the hash (as digest) and the hash function (as opts) to Sign.
Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)
}
Signer is an interface for an opaque private key that can be used for signing operations. For example, an RSA key kept in a hardware module.
type SignerOpts ¶added in go1.4
type SignerOpts interface {
// HashFunc returns an identifier for the hash function used to produce
// the message passed to Signer.Sign, or else zero to indicate that no
// hashing was done.
HashFunc() Hash
}
SignerOpts contains options for signing with a Signer.
2.4.4 - des
des
Package des implements the Data Encryption Standard (DES) and the Triple Data Encryption Algorithm (TDEA) as defined in U.S. Federal Information Processing Standards Publication 46-3.
DES is cryptographically broken and should not be used for secure applications.
常量 ¶
const BlockSize = 8
The DES block size in bytes.
变量
This section is empty.
函数
func NewCipher ¶
func NewCipher(key []byte) (cipher.Block, error)
NewCipher creates and returns a new cipher.Block.
func NewTripleDESCipher ¶
func NewTripleDESCipher(key []byte) (cipher.Block, error)
NewTripleDESCipher creates and returns a new cipher.Block.
类型
type KeySizeError ¶
type KeySizeError int
(KeySizeError) Error ¶
func (k KeySizeError) Error() string
2.4.5 - dsa
dsa
https://pkg.go.dev/crypto/dsa@go1.20.1
Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
The DSA operations in this package are not implemented using constant-time algorithms.
Deprecated: DSA is a legacy algorithm, and modern alternatives such as Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while bigger keys are not widely supported. Note that FIPS 186-5 no longer approves DSA for signature generation.
常量 ¶
This section is empty.
变量
var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
ErrInvalidPublicKey results when a public key is not usable by this code. FIPS is quite strict about the format of DSA keys, but other code may be less so. Thus, when using keys which may have been generated by other code, this error must be handled.
函数
func GenerateKey ¶
func GenerateKey(priv *PrivateKey, rand io.Reader) error
GenerateKey generates a public&private key pair. The Parameters of the PrivateKey must already be valid (see GenerateParameters).
func GenerateParameters ¶
func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error
GenerateParameters puts a random, valid set of DSA parameters into params. This function can take many seconds, even on fast machines.
func Sign ¶
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)
Sign signs an arbitrary length hash (which should be the result of hashing a larger message) using the private key, priv. It returns the signature as a pair of integers. The security of the private key depends on the entropy of rand.
Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated to the byte-length of the subgroup. This function does not perform that truncation itself.
Be aware that calling Sign with an attacker-controlled PrivateKey may require an arbitrary amount of CPU.
func Verify ¶
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool
Verify verifies the signature in r, s of hash using the public key, pub. It reports whether the signature is valid.
Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated to the byte-length of the subgroup. This function does not perform that truncation itself.
类型
type ParameterSizes ¶
type ParameterSizes int
ParameterSizes is an enumeration of the acceptable bit lengths of the primes in a set of DSA parameters. See FIPS 186-3, section 4.2.
const (
L1024N160 ParameterSizes = iota
L2048N224
L2048N256
L3072N256
)
type Parameters ¶
type Parameters struct {
P, Q, G *big.Int
}
Parameters represents the domain parameters for a key. These parameters can be shared across many keys. The bit length of Q must be a multiple of 8.
type PrivateKey ¶
type PrivateKey struct {
PublicKey
X *big.Int
}
PrivateKey represents a DSA private key.
type PublicKey ¶
type PublicKey struct {
Parameters
Y *big.Int
}
PublicKey represents a DSA public key.
2.4.6 - ecdh
ecdh
https://pkg.go.dev/crypto/ecdh@go1.20.1
Package ecdh implements Elliptic Curve Diffie-Hellman over NIST curves and Curve25519.
常量 ¶
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type Curve ¶
type Curve interface {
// GenerateKey generates a new PrivateKey from rand.
GenerateKey(rand io.Reader) (*PrivateKey, error)
// NewPrivateKey checks that key is valid and returns a PrivateKey.
//
// For NIST curves, this follows SEC 1, Version 2.0, Section 2.3.6, which
// amounts to decoding the bytes as a fixed length big endian integer and
// checking that the result is lower than the order of the curve. The zero
// private key is also rejected, as the encoding of the corresponding public
// key would be irregular.
//
// For X25519, this only checks the scalar length.
NewPrivateKey(key []byte) (*PrivateKey, error)
// NewPublicKey checks that key is valid and returns a PublicKey.
//
// For NIST curves, this decodes an uncompressed point according to SEC 1,
// Version 2.0, Section 2.3.4. Compressed encodings and the point at
// infinity are rejected.
//
// For X25519, this only checks the u-coordinate length. Adversarially
// selected public keys can cause ECDH to return an error.
NewPublicKey(key []byte) (*PublicKey, error)
// contains filtered or unexported methods
}
func P256 ¶
func P256() Curve
P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), also known as secp256r1 or prime256v1.
Multiple invocations of this function will return the same value, which can be used for equality checks and switch statements.
func P384 ¶
func P384() Curve
P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4), also known as secp384r1.
Multiple invocations of this function will return the same value, which can be used for equality checks and switch statements.
func P521 ¶
func P521() Curve
P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5), also known as secp521r1.
Multiple invocations of this function will return the same value, which can be used for equality checks and switch statements.
func X25519 ¶
func X25519() Curve
X25519 returns a Curve which implements the X25519 function over Curve25519 (RFC 7748, Section 5).
Multiple invocations of this function will return the same value, so it can be used for equality checks and switch statements.
type PrivateKey ¶
type PrivateKey struct {
// contains filtered or unexported fields
}
PrivateKey is an ECDH private key, usually kept secret.
These keys can be parsed with crypto/x509.ParsePKCS8PrivateKey and encoded with crypto/x509.MarshalPKCS8PrivateKey. For NIST curves, they then need to be converted with crypto/ecdsa.PrivateKey.ECDH after parsing.
(*PrivateKey) Bytes ¶
func (k *PrivateKey) Bytes() []byte
Bytes returns a copy of the encoding of the private key.
(*PrivateKey) Curve ¶
func (k *PrivateKey) Curve() Curve
(*PrivateKey) ECDH ¶
func (k *PrivateKey) ECDH(remote *PublicKey) ([]byte, error)
ECDH performs a ECDH exchange and returns the shared secret.
For NIST curves, this performs ECDH as specified in SEC 1, Version 2.0, Section 3.3.1, and returns the x-coordinate encoded according to SEC 1, Version 2.0, Section 2.3.5. The result is never the point at infinity.
For X25519, this performs ECDH as specified in RFC 7748, Section 6.1. If the result is the all-zero value, ECDH returns an error.
(*PrivateKey) Equal ¶
func (k *PrivateKey) Equal(x crypto.PrivateKey) bool
Equal returns whether x represents the same private key as k.
Note that there can be equivalent private keys with different encodings which would return false from this check but behave the same way as inputs to ECDH.
This check is performed in constant time as long as the key types and their curve match.
(*PrivateKey) Public ¶
func (k *PrivateKey) Public() crypto.PublicKey
Public implements the implicit interface of all standard library private keys. See the docs of crypto.PrivateKey.
(*PrivateKey) PublicKey ¶
func (k *PrivateKey) PublicKey() *PublicKey
type PublicKey ¶
type PublicKey struct {
// contains filtered or unexported fields
}
PublicKey is an ECDH public key, usually a peer’s ECDH share sent over the wire.
These keys can be parsed with crypto/x509.ParsePKIXPublicKey and encoded with crypto/x509.MarshalPKIXPublicKey. For NIST curves, they then need to be converted with crypto/ecdsa.PublicKey.ECDH after parsing.
(*PublicKey) Bytes ¶
func (k *PublicKey) Bytes() []byte
Bytes returns a copy of the encoding of the public key.
(*PublicKey) Curve ¶
func (k *PublicKey) Curve() Curve
(*PublicKey) Equal ¶
func (k *PublicKey) Equal(x crypto.PublicKey) bool
Equal returns whether x represents the same public key as k.
Note that there can be equivalent public keys with different encodings which would return false from this check but behave the same way as inputs to ECDH.
This check is performed in constant time as long as the key types and their curve match.
2.4.7 - ecdsa
ecdsa
https://pkg.go.dev/crypto/ecdsa@go1.20.1
Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as defined in FIPS 186-4 and SEC 1, Version 2.0.
Signatures generated by this package are not deterministic, but entropy is mixed with the private key and the message, achieving the same level of security in case of randomness source failure.
常量 ¶
This section is empty.
变量
This section is empty.
函数
func Sign ¶
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error)
Sign signs a hash (which should be the result of hashing a larger message) using the private key, priv. If the hash is longer than the bit-length of the private key’s curve order, the hash will be truncated to that length. It returns the signature as a pair of integers. Most applications should use SignASN1 instead of dealing directly with r, s.
func SignASN1 ¶added in go1.15
func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error)
SignASN1 signs a hash (which should be the result of hashing a larger message) using the private key, priv. If the hash is longer than the bit-length of the private key’s curve order, the hash will be truncated to that length. It returns the ASN.1 encoded signature.
func Verify ¶
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool
Verify verifies the signature in r, s of hash using the public key, pub. Its return value records whether the signature is valid. Most applications should use VerifyASN1 instead of dealing directly with r, s.
func VerifyASN1 ¶added in go1.15
func VerifyASN1(pub *PublicKey, hash, sig []byte) bool
VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the public key, pub. Its return value records whether the signature is valid.
类型
type PrivateKey ¶
type PrivateKey struct {
PublicKey
D *big.Int
}
PrivateKey represents an ECDSA private key.
func GenerateKey ¶
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error)
GenerateKey generates a public and private key pair.
(*PrivateKey) ECDH ¶added in go1.20
func (k *PrivateKey) ECDH() (*ecdh.PrivateKey, error)
ECDH returns k as a ecdh.PrivateKey. It returns an error if the key is invalid according to the definition of ecdh.Curve.NewPrivateKey, or if the Curve is not supported by crypto/ecdh.
(*PrivateKey) Equal ¶added in go1.15
func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool
Equal reports whether priv and x have the same value.
See PublicKey.Equal for details on how Curve is compared.
(*PrivateKey) Public ¶added in go1.4
func (priv *PrivateKey) Public() crypto.PublicKey
Public returns the public key corresponding to priv.
(*PrivateKey) Sign ¶added in go1.4
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
Sign signs digest with priv, reading randomness from rand. The opts argument is not currently used but, in keeping with the crypto.Signer interface, should be the hash function used to digest the message.
This method implements crypto.Signer, which is an interface to support keys where the private part is kept in, for example, a hardware module. Common uses can use the SignASN1 function in this package directly.
type PublicKey ¶
type PublicKey struct {
elliptic.Curve
X, Y *big.Int
}
PublicKey represents an ECDSA public key.
(*PublicKey) ECDH ¶added in go1.20
func (k *PublicKey) ECDH() (*ecdh.PublicKey, error)
ECDH returns k as a ecdh.PublicKey. It returns an error if the key is invalid according to the definition of ecdh.Curve.NewPublicKey, or if the Curve is not supported by crypto/ecdh.
(*PublicKey) Equal ¶added in go1.15
func (pub *PublicKey) Equal(x crypto.PublicKey) bool
Equal reports whether pub and x have the same value.
Two keys are only considered to have the same value if they have the same Curve value. Note that for example elliptic.P256() and elliptic.P256().Params() are different values, as the latter is a generic not constant time implementation.
2.4.8 - ed25519
ed25519
https://pkg.go.dev/crypto/ed25519@go1.20.1
Package ed25519 implements the Ed25519 signature algorithm. See https://ed25519.cr.yp.to/.
These functions are also compatible with the “Ed25519” function defined in RFC 8032. However, unlike RFC 8032’s formulation, this package’s private key representation includes a public key suffix to make multiple signing operations with the same key more efficient. This package refers to the RFC 8032 private key as the “seed”.
Example (Ed25519ctx) ¶
常量 ¶
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
变量
This section is empty.
函数
func GenerateKey ¶
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error)
GenerateKey generates a public/private key pair using entropy from rand. If rand is nil, crypto/rand.Reader will be used.
func Sign ¶
func Sign(privateKey PrivateKey, message []byte) []byte
Sign signs the message with privateKey and returns a signature. It will panic if len(privateKey) is not PrivateKeySize.
func Verify ¶
func Verify(publicKey PublicKey, message, sig []byte) bool
Verify reports whether sig is a valid signature of message by publicKey. It will panic if len(publicKey) is not PublicKeySize.
func VerifyWithOptions ¶added in go1.20
func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) error
VerifyWithOptions reports whether sig is a valid signature of message by publicKey. A valid signature is indicated by returning a nil error. It will panic if len(publicKey) is not PublicKeySize.
If opts.Hash is crypto.SHA512, the pre-hashed variant Ed25519ph is used and message is expected to be a SHA-512 hash, otherwise opts.Hash must be crypto.Hash(0) and the message must not be hashed, as Ed25519 performs two passes over messages to be signed.
类型
type Options ¶added in go1.20
type Options struct {
// Hash can be zero for regular Ed25519, or crypto.SHA512 for Ed25519ph.
Hash crypto.Hash
// Context, if not empty, selects Ed25519ctx or provides the context string
// for Ed25519ph. It can be at most 255 bytes in length.
Context string
}
Options can be used with PrivateKey.Sign or VerifyWithOptions to select Ed25519 variants.
(*Options) HashFunc ¶added in go1.20
func (o *Options) HashFunc() crypto.Hash
HashFunc returns o.Hash.
type PrivateKey ¶
type PrivateKey []byte
PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
func NewKeyFromSeed ¶
func NewKeyFromSeed(seed []byte) PrivateKey
NewKeyFromSeed calculates a private key from a seed. It will panic if len(seed) is not SeedSize. This function is provided for interoperability with RFC 8032. RFC 8032’s private keys correspond to seeds in this package.
(PrivateKey) Equal ¶added in go1.15
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool
Equal reports whether priv and x have the same value.
(PrivateKey) Public ¶
func (priv PrivateKey) Public() crypto.PublicKey
Public returns the PublicKey corresponding to priv.
(PrivateKey) Seed ¶
func (priv PrivateKey) Seed() []byte
Seed returns the private key seed corresponding to priv. It is provided for interoperability with RFC 8032. RFC 8032’s private keys correspond to seeds in this package.
(PrivateKey) Sign ¶
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error)
Sign signs the given message with priv. rand is ignored.
If opts.HashFunc() is crypto.SHA512, the pre-hashed variant Ed25519ph is used and message is expected to be a SHA-512 hash, otherwise opts.HashFunc() must be crypto.Hash(0) and the message must not be hashed, as Ed25519 performs two passes over messages to be signed.
A value of type Options can be used as opts, or crypto.Hash(0) or crypto.SHA512 directly to select plain Ed25519 or Ed25519ph, respectively.
type PublicKey ¶
type PublicKey []byte
PublicKey is the type of Ed25519 public keys.
(PublicKey) Equal ¶added in go1.15
func (pub PublicKey) Equal(x crypto.PublicKey) bool
Equal reports whether pub and x have the same value.
2.4.9 - elliptic
elliptic
https://pkg.go.dev/crypto/elliptic@go1.20.1
Package elliptic implements the standard NIST P-224, P-256, P-384, and P-521 elliptic curves over prime fields.
The P224(), P256(), P384() and P521() values are necessary to use the crypto/ecdsa package. Most other uses should migrate to the more efficient and safer crypto/ecdh package.
常量 ¶
This section is empty.
变量
This section is empty.
函数
func GenerateKey ¶
func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error)
GenerateKey returns a public/private key pair. The private key is generated using the given reader, which must return random data.
Note: for ECDH, use the GenerateKey methods of the crypto/ecdh package; for ECDSA, use the GenerateKey function of the crypto/ecdsa package.
func Marshal ¶
func Marshal(curve Curve, x, y *big.Int) []byte
Marshal converts a point on the curve into the uncompressed form specified in SEC 1, Version 2.0, Section 2.3.3. If the point is not on the curve (or is the conventional point at infinity), the behavior is undefined.
Note: for ECDH, use the crypto/ecdh package. This function returns an encoding equivalent to that of PublicKey.Bytes in crypto/ecdh.
func MarshalCompressed ¶added in go1.15
func MarshalCompressed(curve Curve, x, y *big.Int) []byte
MarshalCompressed converts a point on the curve into the compressed form specified in SEC 1, Version 2.0, Section 2.3.3. If the point is not on the curve (or is the conventional point at infinity), the behavior is undefined.
func Unmarshal ¶
func Unmarshal(curve Curve, data []byte) (x, y *big.Int)
Unmarshal converts a point, serialized by Marshal, into an x, y pair. It is an error if the point is not in uncompressed form, is not on the curve, or is the point at infinity. On error, x = nil.
Note: for ECDH, use the crypto/ecdh package. This function accepts an encoding equivalent to that of the NewPublicKey methods in crypto/ecdh.
func UnmarshalCompressed ¶added in go1.15
func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int)
UnmarshalCompressed converts a point, serialized by MarshalCompressed, into an x, y pair. It is an error if the point is not in compressed form, is not on the curve, or is the point at infinity. On error, x = nil.
类型
type Curve ¶
type Curve interface {
// Params returns the parameters for the curve.
Params() *CurveParams
// IsOnCurve reports whether the given (x,y) lies on the curve.
//
// Note: this is a low-level unsafe API. For ECDH, use the crypto/ecdh
// package. The NewPublicKey methods of NIST curves in crypto/ecdh accept
// the same encoding as the Unmarshal function, and perform on-curve checks.
IsOnCurve(x, y *big.Int) bool
// Add returns the sum of (x1,y1) and (x2,y2).
//
// Note: this is a low-level unsafe API.
Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int)
// Double returns 2*(x,y).
//
// Note: this is a low-level unsafe API.
Double(x1, y1 *big.Int) (x, y *big.Int)
// ScalarMult returns k*(x,y) where k is an integer in big-endian form.
//
// Note: this is a low-level unsafe API. For ECDH, use the crypto/ecdh
// package. Most uses of ScalarMult can be replaced by a call to the ECDH
// methods of NIST curves in crypto/ecdh.
ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
// ScalarBaseMult returns k*G, where G is the base point of the group
// and k is an integer in big-endian form.
//
// Note: this is a low-level unsafe API. For ECDH, use the crypto/ecdh
// package. Most uses of ScalarBaseMult can be replaced by a call to the
// PrivateKey.PublicKey method in crypto/ecdh.
ScalarBaseMult(k []byte) (x, y *big.Int)
}
A Curve represents a short-form Weierstrass curve with a=-3.
The behavior of Add, Double, and ScalarMult when the input is not a point on the curve is undefined.
Note that the conventional point at infinity (0, 0) is not considered on the curve, although it can be returned by Add, Double, ScalarMult, or ScalarBaseMult (but not the Unmarshal or UnmarshalCompressed functions).
func P224 ¶
func P224() Curve
P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2), also known as secp224r1. The CurveParams.Name of this Curve is “P-224”.
Multiple invocations of this function will return the same value, so it can be used for equality checks and switch statements.
The cryptographic operations are implemented using constant-time algorithms.
func P256 ¶
func P256() Curve
P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is “P-256”.
Multiple invocations of this function will return the same value, so it can be used for equality checks and switch statements.
The cryptographic operations are implemented using constant-time algorithms.
func P384 ¶
func P384() Curve
P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4), also known as secp384r1. The CurveParams.Name of this Curve is “P-384”.
Multiple invocations of this function will return the same value, so it can be used for equality checks and switch statements.
The cryptographic operations are implemented using constant-time algorithms.
func P521 ¶
func P521() Curve
P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5), also known as secp521r1. The CurveParams.Name of this Curve is “P-521”.
Multiple invocations of this function will return the same value, so it can be used for equality checks and switch statements.
The cryptographic operations are implemented using constant-time algorithms.
type CurveParams ¶
type CurveParams struct {
P *big.Int // the order of the underlying field
N *big.Int // the order of the base point
B *big.Int // the constant of the curve equation
Gx, Gy *big.Int // (x,y) of the base point
BitSize int // the size of the underlying field
Name string // the canonical name of the curve
}
CurveParams contains the parameters of an elliptic curve and also provides a generic, non-constant time implementation of Curve.
Note: Custom curves (those not returned by P224(), P256(), P384(), and P521()) are not guaranteed to provide any security property.
(*CurveParams) Add ¶
func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int)
Add implements Curve.Add.
Note: the CurveParams methods are not guaranteed to provide any security property. For ECDH, use the crypto/ecdh package. For ECDSA, use the crypto/ecdsa package with a Curve value returned directly from P224(), P256(), P384(), or P521().
(*CurveParams) Double ¶
func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int)
Double implements Curve.Double.
Note: the CurveParams methods are not guaranteed to provide any security property. For ECDH, use the crypto/ecdh package. For ECDSA, use the crypto/ecdsa package with a Curve value returned directly from P224(), P256(), P384(), or P521().
(*CurveParams) IsOnCurve ¶
func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool
IsOnCurve implements Curve.IsOnCurve.
Note: the CurveParams methods are not guaranteed to provide any security property. For ECDH, use the crypto/ecdh package. For ECDSA, use the crypto/ecdsa package with a Curve value returned directly from P224(), P256(), P384(), or P521().
(*CurveParams) Params ¶
func (curve *CurveParams) Params() *CurveParams
(*CurveParams) ScalarBaseMult ¶
func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int)
ScalarBaseMult implements Curve.ScalarBaseMult.
Note: the CurveParams methods are not guaranteed to provide any security property. For ECDH, use the crypto/ecdh package. For ECDSA, use the crypto/ecdsa package with a Curve value returned directly from P224(), P256(), P384(), or P521().
(*CurveParams) ScalarMult ¶
func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int)
ScalarMult implements Curve.ScalarMult.
Note: the CurveParams methods are not guaranteed to provide any security property. For ECDH, use the crypto/ecdh package. For ECDSA, use the crypto/ecdsa package with a Curve value returned directly from P224(), P256(), P384(), or P521().
2.4.10 - hmac
hmac
https://pkg.go.dev/crypto/hmac@go1.20.1
Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key.
Receivers should be careful to use Equal to compare MACs in order to avoid timing side-channels:
// ValidMAC reports whether messageMAC is a valid HMAC tag for message.
func ValidMAC(message, messageMAC, key []byte) bool {
mac := hmac.New(sha256.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
return hmac.Equal(messageMAC, expectedMAC)
}
常量 ¶
This section is empty.
变量
This section is empty.
函数
func Equal ¶added in go1.1
func Equal(mac1, mac2 []byte) bool
Equal compares two MACs for equality without leaking timing information.
func New ¶
func New(h func() hash.Hash, key []byte) hash.Hash
New returns a new HMAC hash using the given hash.Hash type and key. New functions like sha256.New from crypto/sha256 can be used as h. h must return a new Hash every time it is called. Note that unlike other hash implementations in the standard library, the returned Hash does not implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler.
类型
This section is empty.
2.4.11 - md5
md5
https://pkg.go.dev/crypto/md5@go1.20.1
Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
MD5 is cryptographically broken and should not be used for secure applications.
常量 ¶
const BlockSize = 64
The blocksize of MD5 in bytes.
const Size = 16
The size of an MD5 checksum in bytes.
变量
This section is empty.
函数
func New ¶
func New() hash.Hash
New returns a new hash.Hash computing the MD5 checksum. The Hash also implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal and unmarshal the internal state of the hash.
func Sum ¶added in go1.2
func Sum(data []byte) [Size]byte
Sum returns the MD5 checksum of the data.
类型
This section is empty.
2.4.12 - rand
rand
https://pkg.go.dev/crypto/rand@go1.20.1
Package rand implements a cryptographically secure random number generator.
常量 ¶
This section is empty.
变量
var Reader io.Reader
Reader is a global, shared instance of a cryptographically secure random number generator.
On Linux, FreeBSD, Dragonfly and Solaris, Reader uses getrandom(2) if available, /dev/urandom otherwise. On OpenBSD and macOS, Reader uses getentropy(2). On other Unix-like systems, Reader reads from /dev/urandom. On Windows systems, Reader uses the RtlGenRandom API. On Wasm, Reader uses the Web Crypto API.
函数
func Int ¶
func Int(rand io.Reader, max *big.Int) (n *big.Int, err error)
Int returns a uniform random value in [0, max). It panics if max <= 0.
func Prime ¶
func Prime(rand io.Reader, bits int) (*big.Int, error)
Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any error returned by rand.Read or if bits < 2.
func Read ¶
func Read(b []byte) (n int, err error)
Read is a helper function that calls Reader.Read using io.ReadFull. On return, n == len(b) if and only if err == nil.
类型
This section is empty.
2.4.13 - rc4
rc4
https://pkg.go.dev/crypto/rc4@go1.20.1
Package rc4 implements RC4 encryption, as defined in Bruce Schneier’s Applied Cryptography.
RC4 is cryptographically broken and should not be used for secure applications.
常量 ¶
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type Cipher ¶
type Cipher struct {
// contains filtered or unexported fields
}
A Cipher is an instance of RC4 using a particular key.
func NewCipher ¶
func NewCipher(key []byte) (*Cipher, error)
NewCipher creates and returns a new Cipher. The key argument should be the RC4 key, at least 1 byte and at most 256 bytes.
func (*Cipher)ResetDEPRECATED
(*Cipher) XORKeyStream ¶
func (c *Cipher) XORKeyStream(dst, src []byte)
XORKeyStream sets dst to the result of XORing src with the key stream. Dst and src must overlap entirely or not at all.
type KeySizeError ¶
type KeySizeError int
(KeySizeError) Error ¶
func (k KeySizeError) Error() string
2.4.14 - rsa
rsa
https://pkg.go.dev/crypto/rsa@go1.20.1
Package rsa implements RSA encryption as specified in PKCS #1 and RFC 8017.
RSA is a single, fundamental operation that is used in this package to implement either public-key encryption or public-key signatures.
The original specification for encryption and signatures with RSA is PKCS #1 and the terms “RSA encryption” and “RSA signatures” by default refer to PKCS #1 version 1.5. However, that specification has flaws and new designs should use version 2, usually called by just OAEP and PSS, where possible.
Two sets of interfaces are included in this package. When a more abstract interface isn’t necessary, there are functions for encrypting/decrypting with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract over the public key primitive, the PrivateKey type implements the Decrypter and Signer interfaces from the crypto package.
Operations in this package are implemented using constant-time algorithms, except for GenerateKey, PrivateKey.Precompute, and PrivateKey.Validate. Every other operation only leaks the bit size of the involved values, which all depend on the selected key size.
常量 ¶
const (
// PSSSaltLengthAuto causes the salt in a PSS signature to be as large
// as possible when signing, and to be auto-detected when verifying.
PSSSaltLengthAuto = 0
// PSSSaltLengthEqualsHash causes the salt length to equal the length
// of the hash used in the signature.
PSSSaltLengthEqualsHash = -1
)
变量
var ErrDecryption = errors.New("crypto/rsa: decryption error")
ErrDecryption represents a failure to decrypt a message. It is deliberately vague to avoid adaptive attacks.
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size")
ErrMessageTooLong is returned when attempting to encrypt or sign a message which is too large for the size of the key. When using SignPSS, this can also be returned if the size of the salt is too large.
var ErrVerification = errors.New("crypto/rsa: verification error")
ErrVerification represents a failure to verify a signature. It is deliberately vague to avoid adaptive attacks.
函数
func DecryptOAEP ¶
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)
DecryptOAEP decrypts ciphertext using RSA-OAEP.
OAEP is parameterised by a hash function that is used as a random oracle. Encryption and decryption of a given message must use the same hash function and sha256.New() is a reasonable choice.
The random parameter is legacy and ignored, and it can be as nil.
The label parameter must match the value given when encrypting. See EncryptOAEP for details.
Example ¶
func DecryptPKCS1v15 ¶
func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)
DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5. The random parameter is legacy and ignored, and it can be as nil.
Note that whether this function returns an error or not discloses secret information. If an attacker can cause this function to run repeatedly and learn whether each instance returned an error then they can decrypt and forge signatures as if they had the private key. See DecryptPKCS1v15SessionKey for a way of solving this problem.
func DecryptPKCS1v15SessionKey ¶
func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error
DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS #1 v1.5. The random parameter is legacy and ignored, and it can be as nil. It returns an error if the ciphertext is the wrong length or if the ciphertext is greater than the public modulus. Otherwise, no error is returned. If the padding is valid, the resulting plaintext message is copied into key. Otherwise, key is unchanged. These alternatives occur in constant time. It is intended that the user of this function generate a random session key beforehand and continue the protocol with the resulting value. This will remove any possibility that an attacker can learn any information about the plaintext. See “Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel Bleichenbacher, Advances in Cryptology (Crypto ‘98).
Note that if the session key is too small then it may be possible for an attacker to brute-force it. If they can do that then they can learn whether a random value was used (because it’ll be different for the same ciphertext) and thus whether the padding was correct. This defeats the point of this function. Using at least a 16-byte key will protect against this attack.
Example ¶
func EncryptOAEP ¶
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error)
EncryptOAEP encrypts the given message with RSA-OAEP.
OAEP is parameterised by a hash function that is used as a random oracle. Encryption and decryption of a given message must use the same hash function and sha256.New() is a reasonable choice.
The random parameter is used as a source of entropy to ensure that encrypting the same message twice doesn’t result in the same ciphertext.
The label parameter may contain arbitrary data that will not be encrypted, but which gives important context to the message. For example, if a given public key is used to encrypt two types of messages then distinct label values could be used to ensure that a ciphertext for one purpose cannot be used for another by an attacker. If not required it can be empty.
The message must be no longer than the length of the public modulus minus twice the hash length, minus a further 2.
Example ¶
func EncryptPKCS1v15 ¶
func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS #1 v1.5. The message must be no longer than the length of the public modulus minus 11 bytes.
The random parameter is used as a source of entropy to ensure that encrypting the same message twice doesn’t result in the same ciphertext.
WARNING: use of this function to encrypt plaintexts other than session keys is dangerous. Use RSA OAEP in new protocols.
func SignPKCS1v15 ¶
func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)
SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must be the result of hashing the input message using the given hash function. If hash is zero, hashed is signed directly. This isn’t advisable except for interoperability.
The random parameter is legacy and ignored, and it can be as nil.
This function is deterministic. Thus, if the set of possible messages is small, an attacker may be able to build a map from messages to signatures and identify the signed messages. As ever, signatures provide authenticity, not confidentiality.
Example ¶
func SignPSS ¶added in go1.2
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error)
SignPSS calculates the signature of digest using PSS.
digest must be the result of hashing the input message using the given hash function. The opts argument may be nil, in which case sensible defaults are used. If opts.Hash is set, it overrides hash.
func VerifyPKCS1v15 ¶
func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error
VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature. hashed is the result of hashing the input message using the given hash function and sig is the signature. A valid signature is indicated by returning a nil error. If hash is zero then hashed is used directly. This isn’t advisable except for interoperability.
Example ¶
func VerifyPSS ¶added in go1.2
func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error
VerifyPSS verifies a PSS signature.
A valid signature is indicated by returning a nil error. digest must be the result of hashing the input message using the given hash function. The opts argument may be nil, in which case sensible defaults are used. opts.Hash is ignored.
类型
type CRTValue ¶
type CRTValue struct {
Exp *big.Int // D mod (prime-1).
Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
R *big.Int // product of primes prior to this (inc p and q).
}
CRTValue contains the precomputed Chinese remainder theorem values.
type OAEPOptions ¶added in go1.5
type OAEPOptions struct {
// Hash is the hash function that will be used when generating the mask.
Hash crypto.Hash
// MGFHash is the hash function used for MGF1.
// If zero, Hash is used instead.
MGFHash crypto.Hash
// Label is an arbitrary byte string that must be equal to the value
// used when encrypting.
Label []byte
}
OAEPOptions is an interface for passing options to OAEP decryption using the crypto.Decrypter interface.
type PKCS1v15DecryptOptions ¶added in go1.5
type PKCS1v15DecryptOptions struct {
// SessionKeyLen is the length of the session key that is being
// decrypted. If not zero, then a padding error during decryption will
// cause a random plaintext of this length to be returned rather than
// an error. These alternatives happen in constant time.
SessionKeyLen int
}
PKCS1v15DecryptOptions is for passing options to PKCS #1 v1.5 decryption using the crypto.Decrypter interface.
type PSSOptions ¶added in go1.2
type PSSOptions struct {
// SaltLength controls the length of the salt used in the PSS signature. It
// can either be a positive number of bytes, or one of the special
// PSSSaltLength constants.
SaltLength int
// Hash is the hash function used to generate the message digest. If not
// zero, it overrides the hash function passed to SignPSS. It's required
// when using PrivateKey.Sign.
Hash crypto.Hash
}
PSSOptions contains options for creating and verifying PSS signatures.
(*PSSOptions) HashFunc ¶added in go1.4
func (opts *PSSOptions) HashFunc() crypto.Hash
HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts.
type PrecomputedValues ¶
type PrecomputedValues struct {
Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
Qinv *big.Int // Q^-1 mod P
// CRTValues is used for the 3rd and subsequent primes. Due to a
// historical accident, the CRT for the first two primes is handled
// differently in PKCS #1 and interoperability is sufficiently
// important that we mirror this.
//
// Note: these values are still filled in by Precompute for
// backwards compatibility but are not used. Multi-prime RSA is very rare,
// and is implemented by this package without CRT optimizations to limit
// complexity.
CRTValues []CRTValue
// contains filtered or unexported fields
}
type PrivateKey ¶
type PrivateKey struct {
PublicKey // public part.
D *big.Int // private exponent
Primes []*big.Int // prime factors of N, has >= 2 elements.
// Precomputed contains precomputed values that speed up RSA operations,
// if available. It must be generated by calling PrivateKey.Precompute and
// must not be modified.
Precomputed PrecomputedValues
}
A PrivateKey represents an RSA key
func GenerateKey ¶
func GenerateKey(random io.Reader, bits int) (*PrivateKey, error)
GenerateKey generates an RSA keypair of the given bit size using the random source random (for example, crypto/rand.Reader).
func GenerateMultiPrimeKey ¶
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error)
GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit size and the given random source.
Table 1 in “On the Security of Multi-prime RSA” suggests maximum numbers of primes for a given bit size.
Although the public keys are compatible (actually, indistinguishable) from the 2-prime case, the private keys are not. Thus it may not be possible to export multi-prime private keys in certain formats or to subsequently import them into other code.
This package does not implement CRT optimizations for multi-prime RSA, so the keys with more than two primes will have worse performance.
Note: The use of this function with a number of primes different from two is not recommended for the above security, compatibility, and performance reasons. Use GenerateKey instead.
(*PrivateKey) Decrypt ¶added in go1.5
func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error)
Decrypt decrypts ciphertext with priv. If opts is nil or of type *PKCS1v15DecryptOptions then PKCS #1 v1.5 decryption is performed. Otherwise opts must have type *OAEPOptions and OAEP decryption is done.
(*PrivateKey) Equal ¶added in go1.15
func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool
Equal reports whether priv and x have equivalent values. It ignores Precomputed values.
(*PrivateKey) Precompute ¶
func (priv *PrivateKey) Precompute()
Precompute performs some calculations that speed up private key operations in the future.
(*PrivateKey) Public ¶added in go1.4
func (priv *PrivateKey) Public() crypto.PublicKey
Public returns the public key corresponding to priv.
(*PrivateKey) Sign ¶added in go1.4
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
Sign signs digest with priv, reading randomness from rand. If opts is a *PSSOptions then the PSS algorithm will be used, otherwise PKCS #1 v1.5 will be used. digest must be the result of hashing the input message using opts.HashFunc().
This method implements crypto.Signer, which is an interface to support keys where the private part is kept in, for example, a hardware module. Common uses should use the Sign* functions in this package directly.
(*PrivateKey) Validate ¶
func (priv *PrivateKey) Validate() error
Validate performs basic sanity checks on the key. It returns nil if the key is valid, or else an error describing a problem.
type PublicKey ¶
type PublicKey struct {
N *big.Int // modulus
E int // public exponent
}
A PublicKey represents the public part of an RSA key.
(*PublicKey) Equal ¶added in go1.15
func (pub *PublicKey) Equal(x crypto.PublicKey) bool
Equal reports whether pub and x have the same value.
(*PublicKey) Size ¶added in go1.11
func (pub *PublicKey) Size() int
Size returns the modulus size in bytes. Raw signatures and ciphertexts for or by this public key will have the same size.
2.4.15 - sha1
sha1
https://pkg.go.dev/crypto/sha1@go1.20.1
Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
SHA-1 is cryptographically broken and should not be used for secure applications.
常量 ¶
const BlockSize = 64
The blocksize of SHA-1 in bytes.
const Size = 20
The size of a SHA-1 checksum in bytes.
变量
This section is empty.
函数
func New ¶
func New() hash.Hash
New returns a new hash.Hash computing the SHA1 checksum. The Hash also implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal and unmarshal the internal state of the hash.
func Sum ¶added in go1.2
func Sum(data []byte) [Size]byte
Sum returns the SHA-1 checksum of the data.
类型
This section is empty.
2.4.16 - sha256
sha256
https://pkg.go.dev/crypto/sha256@go1.20.1
Package sha256 implements the SHA224 and SHA256 hash algorithms as defined in FIPS 180-4.
常量 ¶
const BlockSize = 64
The blocksize of SHA256 and SHA224 in bytes.
const Size = 32
The size of a SHA256 checksum in bytes.
const Size224 = 28
The size of a SHA224 checksum in bytes.
变量
This section is empty.
函数
func New ¶
func New() hash.Hash
New returns a new hash.Hash computing the SHA256 checksum. The Hash also implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal and unmarshal the internal state of the hash.
func New224 ¶
func New224() hash.Hash
New224 returns a new hash.Hash computing the SHA224 checksum.
func Sum224 ¶added in go1.2
func Sum224(data []byte) [Size224]byte
Sum224 returns the SHA224 checksum of the data.
func Sum256 ¶added in go1.2
func Sum256(data []byte) [Size]byte
Sum256 returns the SHA256 checksum of the data.
类型
This section is empty.
2.4.17 - sha512
sha512
https://pkg.go.dev/crypto/sha512@go1.20.1
Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 hash algorithms as defined in FIPS 180-4.
All the hash.Hash implementations returned by this package also implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to marshal and unmarshal the internal state of the hash.
常量 ¶
const (
// Size is the size, in bytes, of a SHA-512 checksum.
Size = 64
// Size224 is the size, in bytes, of a SHA-512/224 checksum.
Size224 = 28
// Size256 is the size, in bytes, of a SHA-512/256 checksum.
Size256 = 32
// Size384 is the size, in bytes, of a SHA-384 checksum.
Size384 = 48
// BlockSize is the block size, in bytes, of the SHA-512/224,
// SHA-512/256, SHA-384 and SHA-512 hash functions.
BlockSize = 128
)
变量
This section is empty.
函数
func New ¶
func New() hash.Hash
New returns a new hash.Hash computing the SHA-512 checksum.
func New384 ¶
func New384() hash.Hash
New384 returns a new hash.Hash computing the SHA-384 checksum.
func New512_224 ¶added in go1.5
func New512_224() hash.Hash
New512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
func New512_256 ¶added in go1.5
func New512_256() hash.Hash
New512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
func Sum384 ¶added in go1.2
func Sum384(data []byte) [Size384]byte
Sum384 returns the SHA384 checksum of the data.
func Sum512 ¶added in go1.2
func Sum512(data []byte) [Size]byte
Sum512 returns the SHA512 checksum of the data.
func Sum512_224 ¶added in go1.5
func Sum512_224(data []byte) [Size224]byte
Sum512_224 returns the Sum512/224 checksum of the data.
func Sum512_256 ¶added in go1.5
func Sum512_256(data []byte) [Size256]byte
Sum512_256 returns the Sum512/256 checksum of the data.
类型
This section is empty.
2.4.18 - subtle
subtle
https://pkg.go.dev/crypto/subtle@go1.20.1
Package subtle implements functions that are often useful in cryptographic code but require careful thought to use correctly.
常量 ¶
This section is empty.
变量
This section is empty.
函数
func ConstantTimeByteEq ¶
func ConstantTimeByteEq(x, y uint8) int
ConstantTimeByteEq returns 1 if x == y and 0 otherwise.
func ConstantTimeCompare ¶
func ConstantTimeCompare(x, y []byte) int
ConstantTimeCompare returns 1 if the two slices, x and y, have equal contents and 0 otherwise. The time taken is a function of the length of the slices and is independent of the contents. If the lengths of x and y do not match it returns 0 immediately.
func ConstantTimeCopy ¶
func ConstantTimeCopy(v int, x, y []byte)
ConstantTimeCopy copies the contents of y into x (a slice of equal length) if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v takes any other value.
func ConstantTimeEq ¶
func ConstantTimeEq(x, y int32) int
ConstantTimeEq returns 1 if x == y and 0 otherwise.
func ConstantTimeLessOrEq ¶added in go1.2
func ConstantTimeLessOrEq(x, y int) int
ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. Its behavior is undefined if x or y are negative or > 2**31 - 1.
func ConstantTimeSelect ¶
func ConstantTimeSelect(v, x, y int) int
ConstantTimeSelect returns x if v == 1 and y if v == 0. Its behavior is undefined if v takes any other value.
func XORBytes ¶added in go1.20
func XORBytes(dst, x, y []byte) int
XORBytes sets dst[i] = x[i] ^ y[i] for all i < n = min(len(x), len(y)), returning n, the number of bytes written to dst. If dst does not have length at least n, XORBytes panics without writing anything to dst.
类型
This section is empty.
2.4.19 - tls
tls
https://pkg.go.dev/crypto/tls@go1.20.1
Package tls partially implements TLS 1.2, as specified in RFC 5246, and TLS 1.3, as specified in RFC 8446.
常量 ¶
const (
// TLS 1.0 - 1.2 cipher suites.
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c
TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9
// TLS 1.3 cipher suites.
TLS_AES_128_GCM_SHA256 uint16 = 0x1301
TLS_AES_256_GCM_SHA384 uint16 = 0x1302
TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303
// TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
// that the client is doing version fallback. See RFC 7507.
TLS_FALLBACK_SCSV uint16 = 0x5600
// Legacy names for the corresponding cipher suites with the correct _SHA256
// suffix, retained for backward compatibility.
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
)
A list of cipher suite IDs that are, or have been, implemented by this package.
See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const (
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
VersionTLS13 = 0x0304
// Deprecated: SSLv3 is cryptographically broken, and is no longer
// supported by this package. See golang.org/issue/32716.
VersionSSL30 = 0x0300
)
变量
This section is empty.
函数
func CipherSuiteName ¶added in go1.14
func CipherSuiteName(id uint16) string
CipherSuiteName returns the standard name for the passed cipher suite ID (e.g. “TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256”), or a fallback representation of the ID value if the cipher suite is not implemented by this package.
func Listen ¶
func Listen(network, laddr string, config *Config) (net.Listener, error)
Listen creates a TLS listener accepting connections on the given network address using net.Listen. The configuration config must be non-nil and must include at least one certificate or else set GetCertificate.
func NewListener ¶
func NewListener(inner net.Listener, config *Config) net.Listener
NewListener creates a Listener which accepts connections from an inner Listener and wraps each connection with Server. The configuration config must be non-nil and must include at least one certificate or else set GetCertificate.
类型
type Certificate ¶
type Certificate struct {
Certificate [][]byte
// PrivateKey contains the private key corresponding to the public key in
// Leaf. This must implement crypto.Signer with an RSA, ECDSA or Ed25519 PublicKey.
// For a server up to TLS 1.2, it can also implement crypto.Decrypter with
// an RSA PublicKey.
PrivateKey crypto.PrivateKey
// SupportedSignatureAlgorithms is an optional list restricting what
// signature algorithms the PrivateKey can be used for.
SupportedSignatureAlgorithms []SignatureScheme
// OCSPStaple contains an optional OCSP response which will be served
// to clients that request it.
OCSPStaple []byte
// SignedCertificateTimestamps contains an optional list of Signed
// Certificate Timestamps which will be served to clients that request it.
SignedCertificateTimestamps [][]byte
// Leaf is the parsed form of the leaf certificate, which may be initialized
// using x509.ParseCertificate to reduce per-handshake processing. If nil,
// the leaf certificate will be parsed as needed.
Leaf *x509.Certificate
}
A Certificate is a chain of one or more certificates, leaf first.
func LoadX509KeyPair ¶
func LoadX509KeyPair(certFile, keyFile string) (Certificate, error)
LoadX509KeyPair reads and parses a public/private key pair from a pair of files. The files must contain PEM encoded data. The certificate file may contain intermediate certificates following the leaf certificate to form a certificate chain. On successful return, Certificate.Leaf will be nil because the parsed form of the certificate is not retained.
func X509KeyPair ¶
func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error)
X509KeyPair parses a public/private key pair from a pair of PEM encoded data. On successful return, Certificate.Leaf will be nil because the parsed form of the certificate is not retained.
type CertificateRequestInfo ¶added in go1.8
type CertificateRequestInfo struct {
// AcceptableCAs contains zero or more, DER-encoded, X.501
// Distinguished Names. These are the names of root or intermediate CAs
// that the server wishes the returned certificate to be signed by. An
// empty slice indicates that the server has no preference.
AcceptableCAs [][]byte
// SignatureSchemes lists the signature schemes that the server is
// willing to verify.
SignatureSchemes []SignatureScheme
// Version is the TLS version that was negotiated for this connection.
Version uint16
// contains filtered or unexported fields
}
CertificateRequestInfo contains information from a server’s CertificateRequest message, which is used to demand a certificate and proof of control from a client.
(*CertificateRequestInfo) Context ¶added in go1.17
func (c *CertificateRequestInfo) Context() context.Context
Context returns the context of the handshake that is in progress. This context is a child of the context passed to HandshakeContext, if any, and is canceled when the handshake concludes.
(*CertificateRequestInfo) SupportsCertificate ¶added in go1.14
func (cri *CertificateRequestInfo) SupportsCertificate(c *Certificate) error
SupportsCertificate returns nil if the provided certificate is supported by the server that sent the CertificateRequest. Otherwise, it returns an error describing the reason for the incompatibility.
type CertificateVerificationError ¶added in go1.20
type CertificateVerificationError struct {
// UnverifiedCertificates and its contents should not be modified.
UnverifiedCertificates []*x509.Certificate
Err error
}
CertificateVerificationError is returned when certificate verification fails during the handshake.
(*CertificateVerificationError) Error ¶added in go1.20
func (e *CertificateVerificationError) Error() string
(*CertificateVerificationError) Unwrap ¶added in go1.20
func (e *CertificateVerificationError) Unwrap() error
type CipherSuite ¶added in go1.14
type CipherSuite struct {
ID uint16
Name string
// Supported versions is the list of TLS protocol versions that can
// negotiate this cipher suite.
SupportedVersions []uint16
// Insecure is true if the cipher suite has known security issues
// due to its primitives, design, or implementation.
Insecure bool
}
CipherSuite is a TLS cipher suite. Note that most functions in this package accept and expose cipher suite IDs instead of this type.
func CipherSuites ¶added in go1.14
func CipherSuites() []*CipherSuite
CipherSuites returns a list of cipher suites currently implemented by this package, excluding those with security issues, which are returned by InsecureCipherSuites.
The list is sorted by ID. Note that the default cipher suites selected by this package might depend on logic that can’t be captured by a static list, and might not match those returned by this function.
func InsecureCipherSuites ¶added in go1.14
func InsecureCipherSuites() []*CipherSuite
InsecureCipherSuites returns a list of cipher suites currently implemented by this package and which have security issues.
Most applications should not use the cipher suites in this list, and should only use those returned by CipherSuites.
type ClientAuthType ¶
type ClientAuthType int
ClientAuthType declares the policy the server will follow for TLS Client Authentication.
const (
// NoClientCert indicates that no client certificate should be requested
// during the handshake, and if any certificates are sent they will not
// be verified.
NoClientCert ClientAuthType = iota
// RequestClientCert indicates that a client certificate should be requested
// during the handshake, but does not require that the client send any
// certificates.
RequestClientCert
// RequireAnyClientCert indicates that a client certificate should be requested
// during the handshake, and that at least one certificate is required to be
// sent by the client, but that certificate is not required to be valid.
RequireAnyClientCert
// VerifyClientCertIfGiven indicates that a client certificate should be requested
// during the handshake, but does not require that the client sends a
// certificate. If the client does send a certificate it is required to be
// valid.
VerifyClientCertIfGiven
// RequireAndVerifyClientCert indicates that a client certificate should be requested
// during the handshake, and that at least one valid certificate is required
// to be sent by the client.
RequireAndVerifyClientCert
)
(ClientAuthType) String ¶added in go1.15
func (i ClientAuthType) String() string
type ClientHelloInfo ¶added in go1.4
type ClientHelloInfo struct {
// CipherSuites lists the CipherSuites supported by the client (e.g.
// TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).
CipherSuites []uint16
// ServerName indicates the name of the server requested by the client
// in order to support virtual hosting. ServerName is only set if the
// client is using SNI (see RFC 4366, Section 3.1).
ServerName string
// SupportedCurves lists the elliptic curves supported by the client.
// SupportedCurves is set only if the Supported Elliptic Curves
// Extension is being used (see RFC 4492, Section 5.1.1).
SupportedCurves []CurveID
// SupportedPoints lists the point formats supported by the client.
// SupportedPoints is set only if the Supported Point Formats Extension
// is being used (see RFC 4492, Section 5.1.2).
SupportedPoints []uint8
// SignatureSchemes lists the signature and hash schemes that the client
// is willing to verify. SignatureSchemes is set only if the Signature
// Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1).
SignatureSchemes []SignatureScheme
// SupportedProtos lists the application protocols supported by the client.
// SupportedProtos is set only if the Application-Layer Protocol
// Negotiation Extension is being used (see RFC 7301, Section 3.1).
//
// Servers can select a protocol by setting Config.NextProtos in a
// GetConfigForClient return value.
SupportedProtos []string
// SupportedVersions lists the TLS versions supported by the client.
// For TLS versions less than 1.3, this is extrapolated from the max
// version advertised by the client, so values other than the greatest
// might be rejected if used.
SupportedVersions []uint16
// Conn is the underlying net.Conn for the connection. Do not read
// from, or write to, this connection; that will cause the TLS
// connection to fail.
Conn net.Conn
// contains filtered or unexported fields
}
ClientHelloInfo contains information from a ClientHello message in order to guide application logic in the GetCertificate and GetConfigForClient callbacks.
(*ClientHelloInfo) Context ¶added in go1.17
func (c *ClientHelloInfo) Context() context.Context
Context returns the context of the handshake that is in progress. This context is a child of the context passed to HandshakeContext, if any, and is canceled when the handshake concludes.
(*ClientHelloInfo) SupportsCertificate ¶added in go1.14
func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error
SupportsCertificate returns nil if the provided certificate is supported by the client that sent the ClientHello. Otherwise, it returns an error describing the reason for the incompatibility.
If this ClientHelloInfo was passed to a GetConfigForClient or GetCertificate callback, this method will take into account the associated Config. Note that if GetConfigForClient returns a different Config, the change can’t be accounted for by this method.
This function will call x509.ParseCertificate unless c.Leaf is set, which can incur a significant performance cost.
type ClientSessionCache ¶added in go1.3
type ClientSessionCache interface {
// Get searches for a ClientSessionState associated with the given key.
// On return, ok is true if one was found.
Get(sessionKey string) (session *ClientSessionState, ok bool)
// Put adds the ClientSessionState to the cache with the given key. It might
// get called multiple times in a connection if a TLS 1.3 server provides
// more than one session ticket. If called with a nil *ClientSessionState,
// it should remove the cache entry.
Put(sessionKey string, cs *ClientSessionState)
}
ClientSessionCache is a cache of ClientSessionState objects that can be used by a client to resume a TLS session with a given server. ClientSessionCache implementations should expect to be called concurrently from different goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which are supported via this interface.
func NewLRUClientSessionCache ¶added in go1.3
func NewLRUClientSessionCache(capacity int) ClientSessionCache
NewLRUClientSessionCache returns a ClientSessionCache with the given capacity that uses an LRU strategy. If capacity is < 1, a default capacity is used instead.
type ClientSessionState ¶added in go1.3
type ClientSessionState struct {
// contains filtered or unexported fields
}
ClientSessionState contains the state needed by clients to resume TLS sessions.
type Config ¶
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
// If Rand is nil, TLS uses the cryptographic random reader in package
// crypto/rand.
// The Reader must be safe for use by multiple goroutines.
Rand io.Reader
// Time returns the current time as the number of seconds since the epoch.
// If Time is nil, TLS uses time.Now.
Time func() time.Time
// Certificates contains one or more certificate chains to present to the
// other side of the connection. The first certificate compatible with the
// peer's requirements is selected automatically.
//
// Server configurations must set one of Certificates, GetCertificate or
// GetConfigForClient. Clients doing client-authentication may set either
// Certificates or GetClientCertificate.
//
// Note: if there are multiple Certificates, and they don't have the
// optional field Leaf set, certificate selection will incur a significant
// per-handshake performance cost.
Certificates []Certificate
// NameToCertificate maps from a certificate name to an element of
// Certificates. Note that a certificate name can be of the form
// '*.example.com' and so doesn't have to be a domain name as such.
//
// Deprecated: NameToCertificate only allows associating a single
// certificate with a given name. Leave this field nil to let the library
// select the first compatible chain from Certificates.
NameToCertificate map[string]*Certificate
// GetCertificate returns a Certificate based on the given
// ClientHelloInfo. It will only be called if the client supplies SNI
// information or if Certificates is empty.
//
// If GetCertificate is nil or returns nil, then the certificate is
// retrieved from NameToCertificate. If NameToCertificate is nil, the
// best element of Certificates will be used.
//
// Once a Certificate is returned it should not be modified.
GetCertificate func(*ClientHelloInfo) (*Certificate, error)
// GetClientCertificate, if not nil, is called when a server requests a
// certificate from a client. If set, the contents of Certificates will
// be ignored.
//
// If GetClientCertificate returns an error, the handshake will be
// aborted and that error will be returned. Otherwise
// GetClientCertificate must return a non-nil Certificate. If
// Certificate.Certificate is empty then no certificate will be sent to
// the server. If this is unacceptable to the server then it may abort
// the handshake.
//
// GetClientCertificate may be called multiple times for the same
// connection if renegotiation occurs or if TLS 1.3 is in use.
//
// Once a Certificate is returned it should not be modified.
GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)
// GetConfigForClient, if not nil, is called after a ClientHello is
// received from a client. It may return a non-nil Config in order to
// change the Config that will be used to handle this connection. If
// the returned Config is nil, the original Config will be used. The
// Config returned by this callback may not be subsequently modified.
//
// If GetConfigForClient is nil, the Config passed to Server() will be
// used for all connections.
//
// If SessionTicketKey was explicitly set on the returned Config, or if
// SetSessionTicketKeys was called on the returned Config, those keys will
// be used. Otherwise, the original Config keys will be used (and possibly
// rotated if they are automatically managed).
GetConfigForClient func(*ClientHelloInfo) (*Config, error)
// VerifyPeerCertificate, if not nil, is called after normal
// certificate verification by either a TLS client or server. It
// receives the raw ASN.1 certificates provided by the peer and also
// any verified chains that normal processing found. If it returns a
// non-nil error, the handshake is aborted and that error results.
//
// If normal verification fails then the handshake will abort before
// considering this callback. If normal verification is disabled by
// setting InsecureSkipVerify, or (for a server) when ClientAuth is
// RequestClientCert or RequireAnyClientCert, then this callback will
// be considered but the verifiedChains argument will always be nil.
//
// verifiedChains and its contents should not be modified.
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
// VerifyConnection, if not nil, is called after normal certificate
// verification and after VerifyPeerCertificate by either a TLS client
// or server. If it returns a non-nil error, the handshake is aborted
// and that error results.
//
// If normal verification fails then the handshake will abort before
// considering this callback. This callback will run for all connections
// regardless of InsecureSkipVerify or ClientAuth settings.
VerifyConnection func(ConnectionState) error
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
RootCAs *x509.CertPool
// NextProtos is a list of supported application level protocols, in
// order of preference. If both peers support ALPN, the selected
// protocol will be one from this list, and the connection will fail
// if there is no mutually supported protocol. If NextProtos is empty
// or the peer doesn't support ALPN, the connection will succeed and
// ConnectionState.NegotiatedProtocol will be empty.
NextProtos []string
// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
// in the client's handshake to support virtual hosting unless it is
// an IP address.
ServerName string
// ClientAuth determines the server's policy for
// TLS Client Authentication. The default is NoClientCert.
ClientAuth ClientAuthType
// ClientCAs defines the set of root certificate authorities
// that servers use if required to verify a client certificate
// by the policy in ClientAuth.
ClientCAs *x509.CertPool
// InsecureSkipVerify controls whether a client verifies the server's
// certificate chain and host name. If InsecureSkipVerify is true, crypto/tls
// accepts any certificate presented by the server and any host name in that
// certificate. In this mode, TLS is susceptible to machine-in-the-middle
// attacks unless custom verification is used. This should be used only for
// testing or in combination with VerifyConnection or VerifyPeerCertificate.
InsecureSkipVerify bool
// CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of
// the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.
//
// If CipherSuites is nil, a safe default list is used. The default cipher
// suites might change over time.
CipherSuites []uint16
// PreferServerCipherSuites is a legacy field and has no effect.
//
// It used to control whether the server would follow the client's or the
// server's preference. Servers now select the best mutually supported
// cipher suite based on logic that takes into account inferred client
// hardware, server hardware, and security.
//
// Deprecated: PreferServerCipherSuites is ignored.
PreferServerCipherSuites bool
// SessionTicketsDisabled may be set to true to disable session ticket and
// PSK (resumption) support. Note that on clients, session ticket support is
// also disabled if ClientSessionCache is nil.
SessionTicketsDisabled bool
// SessionTicketKey is used by TLS servers to provide session resumption.
// See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled
// with random data before the first server handshake.
//
// Deprecated: if this field is left at zero, session ticket keys will be
// automatically rotated every day and dropped after seven days. For
// customizing the rotation schedule or synchronizing servers that are
// terminating connections for the same host, use SetSessionTicketKeys.
SessionTicketKey [32]byte
// ClientSessionCache is a cache of ClientSessionState entries for TLS
// session resumption. It is only used by clients.
ClientSessionCache ClientSessionCache
// MinVersion contains the minimum TLS version that is acceptable.
//
// By default, TLS 1.2 is currently used as the minimum when acting as a
// client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum
// supported by this package, both as a client and as a server.
//
// The client-side default can temporarily be reverted to TLS 1.0 by
// including the value "x509sha1=1" in the GODEBUG environment variable.
// Note that this option will be removed in Go 1.19 (but it will still be
// possible to set this field to VersionTLS10 explicitly).
MinVersion uint16
// MaxVersion contains the maximum TLS version that is acceptable.
//
// By default, the maximum version supported by this package is used,
// which is currently TLS 1.3.
MaxVersion uint16
// CurvePreferences contains the elliptic curves that will be used in
// an ECDHE handshake, in preference order. If empty, the default will
// be used. The client will use the first preference as the type for
// its key share in TLS 1.3. This may change in the future.
CurvePreferences []CurveID
// DynamicRecordSizingDisabled disables adaptive sizing of TLS records.
// When true, the largest possible TLS record size is always used. When
// false, the size of TLS records may be adjusted in an attempt to
// improve latency.
DynamicRecordSizingDisabled bool
// Renegotiation controls what types of renegotiation are supported.
// The default, none, is correct for the vast majority of applications.
Renegotiation RenegotiationSupport
// KeyLogWriter optionally specifies a destination for TLS master secrets
// in NSS key log format that can be used to allow external programs
// such as Wireshark to decrypt TLS connections.
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
// Use of KeyLogWriter compromises security and should only be
// used for debugging.
KeyLogWriter io.Writer
// contains filtered or unexported fields
}
A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified. A Config may be reused; the tls package will also not modify it.
func (*Config)BuildNameToCertificateDEPRECATED
(*Config) Clone ¶added in go1.8
func (c *Config) Clone() *Config
Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a Config that is being used concurrently by a TLS client or server.
(*Config) SetSessionTicketKeys ¶added in go1.5
func (c *Config) SetSessionTicketKeys(keys [][32]byte)
SetSessionTicketKeys updates the session ticket keys for a server.
The first key will be used when creating new tickets, while all keys can be used for decrypting tickets. It is safe to call this function while the server is running in order to rotate the session ticket keys. The function will panic if keys is empty.
Calling this function will turn off automatic session ticket key rotation.
If multiple servers are terminating connections for the same host they should all have the same session ticket keys. If the session ticket keys leaks, previously recorded and future TLS connections using those keys might be compromised.
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
A Conn represents a secured connection. It implements the net.Conn interface.
func Client ¶
func Client(conn net.Conn, config *Config) *Conn
Client returns a new TLS client side connection using conn as the underlying transport. The config cannot be nil: users must set either ServerName or InsecureSkipVerify in the config.
func Dial ¶
func Dial(network, addr string, config *Config) (*Conn, error)
Dial connects to the given network address using net.Dial and then initiates a TLS handshake, returning the resulting TLS connection. Dial interprets a nil configuration as equivalent to the zero configuration; see the documentation of Config for the defaults.
func DialWithDialer ¶added in go1.3
func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error)
DialWithDialer connects to the given network address using dialer.Dial and then initiates a TLS handshake, returning the resulting TLS connection. Any timeout or deadline given in the dialer apply to connection and TLS handshake as a whole.
DialWithDialer interprets a nil configuration as equivalent to the zero configuration; see the documentation of Config for the defaults.
DialWithDialer uses context.Background internally; to specify the context, use Dialer.DialContext with NetDialer set to the desired dialer.
func Server ¶
func Server(conn net.Conn, config *Config) *Conn
Server returns a new TLS server side connection using conn as the underlying transport. The configuration config must be non-nil and must include at least one certificate or else set GetCertificate.
(*Conn) Close ¶
func (c *Conn) Close() error
Close closes the connection.
(*Conn) CloseWrite ¶added in go1.8
func (c *Conn) CloseWrite() error
CloseWrite shuts down the writing side of the connection. It should only be called once the handshake has completed and does not call CloseWrite on the underlying connection. Most callers should just use Close.
(*Conn) ConnectionState ¶
func (c *Conn) ConnectionState() ConnectionState
ConnectionState returns basic TLS details about the connection.
(*Conn) Handshake ¶
func (c *Conn) Handshake() error
Handshake runs the client or server handshake protocol if it has not yet been run.
Most uses of this package need not call Handshake explicitly: the first Read or Write will call it automatically.
For control over canceling or setting a timeout on a handshake, use HandshakeContext or the Dialer’s DialContext method instead.
(*Conn) HandshakeContext ¶added in go1.17
func (c *Conn) HandshakeContext(ctx context.Context) error
HandshakeContext runs the client or server handshake protocol if it has not yet been run.
The provided Context must be non-nil. If the context is canceled before the handshake is complete, the handshake is interrupted and an error is returned. Once the handshake has completed, cancellation of the context will not affect the connection.
Most uses of this package need not call HandshakeContext explicitly: the first Read or Write will call it automatically.
(*Conn) LocalAddr ¶
func (c *Conn) LocalAddr() net.Addr
LocalAddr returns the local network address.
(*Conn) NetConn ¶added in go1.18
func (c *Conn) NetConn() net.Conn
NetConn returns the underlying connection that is wrapped by c. Note that writing to or reading from this connection directly will corrupt the TLS session.
(*Conn) OCSPResponse ¶
func (c *Conn) OCSPResponse() []byte
OCSPResponse returns the stapled OCSP response from the TLS server, if any. (Only valid for client connections.)
(*Conn) Read ¶
func (c *Conn) Read(b []byte) (int, error)
Read reads data from the connection.
As Read calls Handshake, in order to prevent indefinite blocking a deadline must be set for both Read and Write before Read is called when the handshake has not yet completed. See SetDeadline, SetReadDeadline, and SetWriteDeadline.
(*Conn) RemoteAddr ¶
func (c *Conn) RemoteAddr() net.Addr
RemoteAddr returns the remote network address.
(*Conn) SetDeadline ¶
func (c *Conn) SetDeadline(t time.Time) error
SetDeadline sets the read and write deadlines associated with the connection. A zero value for t means Read and Write will not time out. After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
(*Conn) SetReadDeadline ¶
func (c *Conn) SetReadDeadline(t time.Time) error
SetReadDeadline sets the read deadline on the underlying connection. A zero value for t means Read will not time out.
(*Conn) SetWriteDeadline ¶
func (c *Conn) SetWriteDeadline(t time.Time) error
SetWriteDeadline sets the write deadline on the underlying connection. A zero value for t means Write will not time out. After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
(*Conn) VerifyHostname ¶
func (c *Conn) VerifyHostname(host string) error
VerifyHostname checks that the peer certificate chain is valid for connecting to host. If so, it returns nil; if not, it returns an error describing the problem.
(*Conn) Write ¶
func (c *Conn) Write(b []byte) (int, error)
Write writes data to the connection.
As Write calls Handshake, in order to prevent indefinite blocking a deadline must be set for both Read and Write before Write is called when the handshake has not yet completed. See SetDeadline, SetReadDeadline, and SetWriteDeadline.
type ConnectionState ¶
type ConnectionState struct {
// Version is the TLS version used by the connection (e.g. VersionTLS12).
Version uint16
// HandshakeComplete is true if the handshake has concluded.
HandshakeComplete bool
// DidResume is true if this connection was successfully resumed from a
// previous session with a session ticket or similar mechanism.
DidResume bool
// CipherSuite is the cipher suite negotiated for the connection (e.g.
// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256).
CipherSuite uint16
// NegotiatedProtocol is the application protocol negotiated with ALPN.
NegotiatedProtocol string
// NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation.
//
// Deprecated: this value is always true.
NegotiatedProtocolIsMutual bool
// ServerName is the value of the Server Name Indication extension sent by
// the client. It's available both on the server and on the client side.
ServerName string
// PeerCertificates are the parsed certificates sent by the peer, in the
// order in which they were sent. The first element is the leaf certificate
// that the connection is verified against.
//
// On the client side, it can't be empty. On the server side, it can be
// empty if Config.ClientAuth is not RequireAnyClientCert or
// RequireAndVerifyClientCert.
//
// PeerCertificates and its contents should not be modified.
PeerCertificates []*x509.Certificate
// VerifiedChains is a list of one or more chains where the first element is
// PeerCertificates[0] and the last element is from Config.RootCAs (on the
// client side) or Config.ClientCAs (on the server side).
//
// On the client side, it's set if Config.InsecureSkipVerify is false. On
// the server side, it's set if Config.ClientAuth is VerifyClientCertIfGiven
// (and the peer provided a certificate) or RequireAndVerifyClientCert.
//
// VerifiedChains and its contents should not be modified.
VerifiedChains [][]*x509.Certificate
// SignedCertificateTimestamps is a list of SCTs provided by the peer
// through the TLS handshake for the leaf certificate, if any.
SignedCertificateTimestamps [][]byte
// OCSPResponse is a stapled Online Certificate Status Protocol (OCSP)
// response provided by the peer for the leaf certificate, if any.
OCSPResponse []byte
// TLSUnique contains the "tls-unique" channel binding value (see RFC 5929,
// Section 3). This value will be nil for TLS 1.3 connections and for all
// resumed connections.
//
// Deprecated: there are conditions in which this value might not be unique
// to a connection. See the Security Considerations sections of RFC 5705 and
// RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
TLSUnique []byte
// contains filtered or unexported fields
}
ConnectionState records basic TLS details about the connection.
(*ConnectionState) ExportKeyingMaterial ¶added in go1.11
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error)
ExportKeyingMaterial returns length bytes of exported key material in a new slice as defined in RFC 5705. If context is nil, it is not used as part of the seed. If the connection was set to allow renegotiation via Config.Renegotiation, this function will return an error.
type CurveID ¶added in go1.3
type CurveID uint16
CurveID is the type of a TLS identifier for an elliptic curve. See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
In TLS 1.3, this type is called NamedGroup, but at this time this library only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.
const (
CurveP256 CurveID = 23
CurveP384 CurveID = 24
CurveP521 CurveID = 25
X25519 CurveID = 29
)
(CurveID) String ¶added in go1.15
func (i CurveID) String() string
type Dialer ¶added in go1.15
type Dialer struct {
// NetDialer is the optional dialer to use for the TLS connections'
// underlying TCP connections.
// A nil NetDialer is equivalent to the net.Dialer zero value.
NetDialer *net.Dialer
// Config is the TLS configuration to use for new connections.
// A nil configuration is equivalent to the zero
// configuration; see the documentation of Config for the
// defaults.
Config *Config
}
Dialer dials TLS connections given a configuration and a Dialer for the underlying connection.
(*Dialer) Dial ¶added in go1.15
func (d *Dialer) Dial(network, addr string) (net.Conn, error)
Dial connects to the given network address and initiates a TLS handshake, returning the resulting TLS connection.
The returned Conn, if any, will always be of type *Conn.
Dial uses context.Background internally; to specify the context, use DialContext.
(*Dialer) DialContext ¶added in go1.15
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error)
DialContext connects to the given network address and initiates a TLS handshake, returning the resulting TLS connection.
The provided Context must be non-nil. If the context expires before the connection is complete, an error is returned. Once successfully connected, any expiration of the context will not affect the connection.
The returned Conn, if any, will always be of type *Conn.
type RecordHeaderError ¶added in go1.6
type RecordHeaderError struct {
// Msg contains a human readable string that describes the error.
Msg string
// RecordHeader contains the five bytes of TLS record header that
// triggered the error.
RecordHeader [5]byte
// Conn provides the underlying net.Conn in the case that a client
// sent an initial handshake that didn't look like TLS.
// It is nil if there's already been a handshake or a TLS alert has
// been written to the connection.
Conn net.Conn
}
RecordHeaderError is returned when a TLS record header is invalid.
(RecordHeaderError) Error ¶added in go1.6
func (e RecordHeaderError) Error() string
type RenegotiationSupport ¶added in go1.7
type RenegotiationSupport int
RenegotiationSupport enumerates the different levels of support for TLS renegotiation. TLS renegotiation is the act of performing subsequent handshakes on a connection after the first. This significantly complicates the state machine and has been the source of numerous, subtle security issues. Initiating a renegotiation is not supported, but support for accepting renegotiation requests may be enabled.
Even when enabled, the server may not change its identity between handshakes (i.e. the leaf certificate must be the same). Additionally, concurrent handshake and application data flow is not permitted so renegotiation can only be used with protocols that synchronise with the renegotiation, such as HTTPS.
Renegotiation is not defined in TLS 1.3.
const (
// RenegotiateNever disables renegotiation.
RenegotiateNever RenegotiationSupport = iota
// RenegotiateOnceAsClient allows a remote server to request
// renegotiation once per connection.
RenegotiateOnceAsClient
// RenegotiateFreelyAsClient allows a remote server to repeatedly
// request renegotiation.
RenegotiateFreelyAsClient
)
type SignatureScheme ¶added in go1.8
type SignatureScheme uint16
SignatureScheme identifies a signature algorithm supported by TLS. See RFC 8446, Section 4.2.3.
const (
// RSASSA-PKCS1-v1_5 algorithms.
PKCS1WithSHA256 SignatureScheme = 0x0401
PKCS1WithSHA384 SignatureScheme = 0x0501
PKCS1WithSHA512 SignatureScheme = 0x0601
// RSASSA-PSS algorithms with public key OID rsaEncryption.
PSSWithSHA256 SignatureScheme = 0x0804
PSSWithSHA384 SignatureScheme = 0x0805
PSSWithSHA512 SignatureScheme = 0x0806
// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
ECDSAWithP256AndSHA256 SignatureScheme = 0x0403
ECDSAWithP384AndSHA384 SignatureScheme = 0x0503
ECDSAWithP521AndSHA512 SignatureScheme = 0x0603
// EdDSA algorithms.
Ed25519 SignatureScheme = 0x0807
// Legacy signature and hash algorithms for TLS 1.2.
PKCS1WithSHA1 SignatureScheme = 0x0201
ECDSAWithSHA1 SignatureScheme = 0x0203
)
(SignatureScheme) String ¶added in go1.15
func (i SignatureScheme) String() string
Notes
Bugs
- The crypto/tls package only implements some countermeasures against Lucky13 attacks on CBC-mode encryption, and only on SHA1 variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
2.4.20 - x509
x509
https://pkg.go.dev/crypto/x509@go1.20.1
Package x509 implements a subset of the X.509 standard.
It allows parsing and generating certificates, certificate signing requests, certificate revocation lists, and encoded public and private keys. It provides a certificate verifier, complete with a chain builder.
The package targets the X.509 technical profile defined by the IETF (RFC 2459/3280/5280), and as further restricted by the CA/Browser Forum Baseline Requirements. There is minimal support for features outside of these profiles, as the primary goal of the package is to provide compatibility with the publicly trusted TLS certificate ecosystem and its policies and constraints.
On macOS and Windows, certificate verification is handled by system APIs, but the package aims to apply consistent validation rules across operating systems.
常量 ¶
This section is empty.
变量
var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
ErrUnsupportedAlgorithm results from attempting to perform an operation that involves algorithms that are not currently implemented.
var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
IncorrectPasswordError is returned when an incorrect password is detected.
函数
func CreateCertificate ¶
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv any) ([]byte, error)
CreateCertificate creates a new X.509 v3 certificate based on a template. The following members of template are currently used:
- AuthorityKeyId
- BasicConstraintsValid
- CRLDistributionPoints
- DNSNames
- EmailAddresses
- ExcludedDNSDomains
- ExcludedEmailAddresses
- ExcludedIPRanges
- ExcludedURIDomains
- ExtKeyUsage
- ExtraExtensions
- IPAddresses
- IsCA
- IssuingCertificateURL
- KeyUsage
- MaxPathLen
- MaxPathLenZero
- NotAfter
- NotBefore
- OCSPServer
- PermittedDNSDomains
- PermittedDNSDomainsCritical
- PermittedEmailAddresses
- PermittedIPRanges
- PermittedURIDomains
- PolicyIdentifiers
- SerialNumber
- SignatureAlgorithm
- Subject
- SubjectKeyId
- URIs
- UnknownExtKeyUsage
The certificate is signed by parent. If parent is equal to template then the certificate is self-signed. The parameter pub is the public key of the certificate to be generated and priv is the private key of the signer.
The returned slice is the certificate in DER encoding.
The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey and ed25519.PublicKey. pub must be a supported key type, and priv must be a crypto.Signer with a supported public key.
The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any, unless the resulting certificate is self-signed. Otherwise the value from template will be used.
If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId will be generated from the hash of the public key.
func CreateCertificateRequest ¶added in go1.3
func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error)
CreateCertificateRequest creates a new certificate request based on a template. The following members of template are used:
- SignatureAlgorithm
- Subject
- DNSNames
- EmailAddresses
- IPAddresses
- URIs
- ExtraExtensions
- Attributes (deprecated)
priv is the private key to sign the CSR with, and the corresponding public key will be included in the CSR. It must implement crypto.Signer and its Public() method must return a *rsa.PublicKey or a *ecdsa.PublicKey or a ed25519.PublicKey. (A *rsa.PrivateKey, *ecdsa.PrivateKey or ed25519.PrivateKey satisfies this.)
The returned slice is the certificate request in DER encoding.
func CreateRevocationList ¶added in go1.15
func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Certificate, priv crypto.Signer) ([]byte, error)
CreateRevocationList creates a new X.509 v2 Certificate Revocation List, according to RFC 5280, based on template.
The CRL is signed by priv which should be the private key associated with the public key in the issuer certificate.
The issuer may not be nil, and the crlSign bit must be set in KeyUsage in order to use it as a CRL issuer.
The issuer distinguished name CRL field and authority key identifier extension are populated using the issuer certificate. issuer must have SubjectKeyId set.
funcDecryptPEMBlockDEPRECATEDadded in go1.1
funcEncryptPEMBlockDEPRECATEDadded in go1.1
funcIsEncryptedPEMBlockDEPRECATEDadded in go1.1
func MarshalECPrivateKey ¶added in go1.2
func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error)
MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “EC PRIVATE KEY”. For a more flexible key format which is not EC specific, use MarshalPKCS8PrivateKey.
func MarshalPKCS1PrivateKey ¶
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte
MarshalPKCS1PrivateKey converts an RSA private key to PKCS #1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “RSA PRIVATE KEY”. For a more flexible key format which is not RSA specific, use MarshalPKCS8PrivateKey.
func MarshalPKCS1PublicKey ¶added in go1.10
func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte
MarshalPKCS1PublicKey converts an RSA public key to PKCS #1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “RSA PUBLIC KEY”.
func MarshalPKCS8PrivateKey ¶added in go1.10
func MarshalPKCS8PrivateKey(key any) ([]byte, error)
MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form.
The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey (not a pointer), and *ecdh.PrivateKey. Unsupported key types result in an error.
This kind of key is commonly encoded in PEM blocks of type “PRIVATE KEY”.
func MarshalPKIXPublicKey ¶
func MarshalPKIXPublicKey(pub any) ([]byte, error)
MarshalPKIXPublicKey converts a public key to PKIX, ASN.1 DER form. The encoded public key is a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1).
The following key types are currently supported: *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey (not a pointer), and *ecdh.PublicKey. Unsupported key types result in an error.
This kind of key is commonly encoded in PEM blocks of type “PUBLIC KEY”.
funcParseCRLDEPRECATED
funcParseDERCRLDEPRECATED
func ParseECPrivateKey ¶added in go1.1
func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error)
ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “EC PRIVATE KEY”.
func ParsePKCS1PrivateKey ¶
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error)
ParsePKCS1PrivateKey parses an RSA private key in PKCS #1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “RSA PRIVATE KEY”.
func ParsePKCS1PublicKey ¶added in go1.10
func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error)
ParsePKCS1PublicKey parses an RSA public key in PKCS #1, ASN.1 DER form.
This kind of key is commonly encoded in PEM blocks of type “RSA PUBLIC KEY”.
func ParsePKCS8PrivateKey ¶
func ParsePKCS8PrivateKey(der []byte) (key any, err error)
ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form.
It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, a ed25519.PrivateKey (not a pointer), or a *ecdh.PublicKey (for X25519). More types might be supported in the future.
This kind of key is commonly encoded in PEM blocks of type “PRIVATE KEY”.
func ParsePKIXPublicKey ¶
func ParsePKIXPublicKey(derBytes []byte) (pub any, err error)
ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form. The encoded public key is a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1).
It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey (not a pointer), or *ecdh.PublicKey (for X25519). More types might be supported in the future.
This kind of key is commonly encoded in PEM blocks of type “PUBLIC KEY”.
func SetFallbackRoots ¶added in go1.20
func SetFallbackRoots(roots *CertPool)
SetFallbackRoots sets the roots to use during certificate verification, if no custom roots are specified and a platform verifier or a system certificate pool is not available (for instance in a container which does not have a root certificate bundle). SetFallbackRoots will panic if roots is nil.
SetFallbackRoots may only be called once, if called multiple times it will panic.
The fallback behavior can be forced on all platforms, even when there is a system certificate pool, by setting GODEBUG=x509usefallbackroots=1 (note that on Windows and macOS this will disable usage of the platform verification APIs and cause the pure Go verifier to be used). Setting x509usefallbackroots=1 without calling SetFallbackRoots has no effect.
类型
type CertPool ¶
type CertPool struct {
// contains filtered or unexported fields
}
CertPool is a set of certificates.
func NewCertPool ¶
func NewCertPool() *CertPool
NewCertPool returns a new, empty CertPool.
func SystemCertPool ¶added in go1.7
func SystemCertPool() (*CertPool, error)
SystemCertPool returns a copy of the system cert pool.
On Unix systems other than macOS the environment variables SSL_CERT_FILE and SSL_CERT_DIR can be used to override the system default locations for the SSL certificate file and SSL certificate files directory, respectively. The latter can be a colon-separated list.
Any mutations to the returned pool are not written to disk and do not affect any other pool returned by SystemCertPool.
New changes in the system cert pool might not be reflected in subsequent calls.
(*CertPool) AddCert ¶
func (s *CertPool) AddCert(cert *Certificate)
AddCert adds a certificate to a pool.
(*CertPool) AppendCertsFromPEM ¶
func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool)
AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. It appends any certificates found to s and reports whether any certificates were successfully parsed.
On many Linux systems, /etc/ssl/cert.pem will contain the system wide set of root CAs in a format suitable for this function.
(*CertPool) Clone ¶added in go1.19
func (s *CertPool) Clone() *CertPool
Clone returns a copy of s.
(*CertPool) Equal ¶added in go1.19
func (s *CertPool) Equal(other *CertPool) bool
Equal reports whether s and other are equal.
func (*CertPool)SubjectsDEPRECATED
type Certificate ¶
type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
RawSubject []byte // DER encoded Subject
RawIssuer []byte // DER encoded Issuer
Signature []byte
SignatureAlgorithm SignatureAlgorithm
PublicKeyAlgorithm PublicKeyAlgorithm
PublicKey any
Version int
SerialNumber *big.Int
Issuer pkix.Name
Subject pkix.Name
NotBefore, NotAfter time.Time // Validity bounds.
KeyUsage KeyUsage
// Extensions contains raw X.509 extensions. When parsing certificates,
// this can be used to extract non-critical extensions that are not
// parsed by this package. When marshaling certificates, the Extensions
// field is ignored, see ExtraExtensions.
Extensions []pkix.Extension
// ExtraExtensions contains extensions to be copied, raw, into any
// marshaled certificates. Values override any extensions that would
// otherwise be produced based on the other fields. The ExtraExtensions
// field is not populated when parsing certificates, see Extensions.
ExtraExtensions []pkix.Extension
// UnhandledCriticalExtensions contains a list of extension IDs that
// were not (fully) processed when parsing. Verify will fail if this
// slice is non-empty, unless verification is delegated to an OS
// library which understands all the critical extensions.
//
// Users can access these extensions using Extensions and can remove
// elements from this slice if they believe that they have been
// handled.
UnhandledCriticalExtensions []asn1.ObjectIdentifier
ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
// BasicConstraintsValid indicates whether IsCA, MaxPathLen,
// and MaxPathLenZero are valid.
BasicConstraintsValid bool
IsCA bool
// MaxPathLen and MaxPathLenZero indicate the presence and
// value of the BasicConstraints' "pathLenConstraint".
//
// When parsing a certificate, a positive non-zero MaxPathLen
// means that the field was specified, -1 means it was unset,
// and MaxPathLenZero being true mean that the field was
// explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false
// should be treated equivalent to -1 (unset).
//
// When generating a certificate, an unset pathLenConstraint
// can be requested with either MaxPathLen == -1 or using the
// zero value for both MaxPathLen and MaxPathLenZero.
MaxPathLen int
// MaxPathLenZero indicates that BasicConstraintsValid==true
// and MaxPathLen==0 should be interpreted as an actual
// maximum path length of zero. Otherwise, that combination is
// interpreted as MaxPathLen not being set.
MaxPathLenZero bool
SubjectKeyId []byte
AuthorityKeyId []byte
// RFC 5280, 4.2.2.1 (Authority Information Access)
OCSPServer []string
IssuingCertificateURL []string
// Subject Alternate Name values. (Note that these values may not be valid
// if invalid values were contained within a parsed certificate. For
// example, an element of DNSNames may not be a valid DNS domain name.)
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
URIs []*url.URL
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
ExcludedDNSDomains []string
PermittedIPRanges []*net.IPNet
ExcludedIPRanges []*net.IPNet
PermittedEmailAddresses []string
ExcludedEmailAddresses []string
PermittedURIDomains []string
ExcludedURIDomains []string
// CRL Distribution Points
CRLDistributionPoints []string
PolicyIdentifiers []asn1.ObjectIdentifier
}
A Certificate represents an X.509 certificate.
func ParseCertificate ¶
func ParseCertificate(der []byte) (*Certificate, error)
ParseCertificate parses a single certificate from the given ASN.1 DER data.
func ParseCertificates ¶
func ParseCertificates(der []byte) ([]*Certificate, error)
ParseCertificates parses one or more certificates from the given ASN.1 DER data. The certificates must be concatenated with no intermediate padding.
func (*Certificate)CheckCRLSignatureDEPRECATED
(*Certificate) CheckSignature ¶
func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error
CheckSignature verifies that signature is a valid signature over signed from c’s public key.
This is a low-level API that performs no validity checks on the certificate.
MD5WithRSA signatures are rejected, while SHA1WithRSA and ECDSAWithSHA1 signatures are currently accepted.
(*Certificate) CheckSignatureFrom ¶
func (c *Certificate) CheckSignatureFrom(parent *Certificate) error
CheckSignatureFrom verifies that the signature on c is a valid signature from parent.
This is a low-level API that performs very limited checks, and not a full path verifier. Most users should use Certificate.Verify instead.
func (*Certificate)CreateCRLDEPRECATED
(*Certificate) Equal ¶
func (c *Certificate) Equal(other *Certificate) bool
(*Certificate) Verify ¶
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error)
Verify attempts to verify c by building one or more chains from c to a certificate in opts.Roots, using certificates in opts.Intermediates if needed. If successful, it returns one or more chains where the first element of the chain is c and the last element is from opts.Roots.
If opts.Roots is nil, the platform verifier might be used, and verification details might differ from what is described below. If system roots are unavailable the returned error will be of type SystemRootsError.
Name constraints in the intermediates will be applied to all names claimed in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim example.com if an intermediate doesn’t permit it, even if example.com is not the name being validated. Note that DirectoryName constraints are not supported.
Name constraint validation follows the rules from RFC 5280, with the addition that DNS name constraints may use the leading period format defined for emails and URIs. When a constraint has a leading period it indicates that at least one additional label must be prepended to the constrained name to be considered valid.
Extended Key Usage values are enforced nested down a chain, so an intermediate or root that enumerates EKUs prevents a leaf from asserting an EKU not in that list. (While this is not specified, it is common practice in order to limit the types of certificates a CA can issue.)
Certificates that use SHA1WithRSA and ECDSAWithSHA1 signatures are not supported, and will not be used to build chains.
Certificates other than c in the returned chains should not be modified.
WARNING: this function doesn’t do any revocation checking.
(*Certificate) VerifyHostname ¶
func (c *Certificate) VerifyHostname(h string) error
VerifyHostname returns nil if c is a valid certificate for the named host. Otherwise it returns an error describing the mismatch.
IP addresses can be optionally enclosed in square brackets and are checked against the IPAddresses field. Other names are checked case insensitively against the DNSNames field. If the names are valid hostnames, the certificate fields can have a wildcard as the left-most label.
Note that the legacy Common Name field is ignored.
type CertificateInvalidError ¶
type CertificateInvalidError struct {
Cert *Certificate
Reason InvalidReason
Detail string
}
CertificateInvalidError results when an odd error occurs. Users of this library probably want to handle all these errors uniformly.
(CertificateInvalidError) Error ¶
func (e CertificateInvalidError) Error() string
type CertificateRequest ¶added in go1.3
type CertificateRequest struct {
Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature).
RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
RawSubject []byte // DER encoded Subject.
Version int
Signature []byte
SignatureAlgorithm SignatureAlgorithm
PublicKeyAlgorithm PublicKeyAlgorithm
PublicKey any
Subject pkix.Name
// Attributes contains the CSR attributes that can parse as
// pkix.AttributeTypeAndValueSET.
//
// Deprecated: Use Extensions and ExtraExtensions instead for parsing and
// generating the requestedExtensions attribute.
Attributes []pkix.AttributeTypeAndValueSET
// Extensions contains all requested extensions, in raw form. When parsing
// CSRs, this can be used to extract extensions that are not parsed by this
// package.
Extensions []pkix.Extension
// ExtraExtensions contains extensions to be copied, raw, into any CSR
// marshaled by CreateCertificateRequest. Values override any extensions
// that would otherwise be produced based on the other fields but are
// overridden by any extensions specified in Attributes.
//
// The ExtraExtensions field is not populated by ParseCertificateRequest,
// see Extensions instead.
ExtraExtensions []pkix.Extension
// Subject Alternate Name values.
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
URIs []*url.URL
}
CertificateRequest represents a PKCS #10, certificate signature request.
func ParseCertificateRequest ¶added in go1.3
func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error)
ParseCertificateRequest parses a single certificate request from the given ASN.1 DER data.
(*CertificateRequest) CheckSignature ¶added in go1.5
func (c *CertificateRequest) CheckSignature() error
CheckSignature reports whether the signature on c is valid.
type ConstraintViolationError ¶
type ConstraintViolationError struct{}
ConstraintViolationError results when a requested usage is not permitted by a certificate. For example: checking a signature when the public key isn’t a certificate signing key.
(ConstraintViolationError) Error ¶
func (ConstraintViolationError) Error() string
type ExtKeyUsage ¶
type ExtKeyUsage int
ExtKeyUsage represents an extended set of actions that are valid for a given key. Each of the ExtKeyUsage* constants define a unique action.
const (
ExtKeyUsageAny ExtKeyUsage = iota
ExtKeyUsageServerAuth
ExtKeyUsageClientAuth
ExtKeyUsageCodeSigning
ExtKeyUsageEmailProtection
ExtKeyUsageIPSECEndSystem
ExtKeyUsageIPSECTunnel
ExtKeyUsageIPSECUser
ExtKeyUsageTimeStamping
ExtKeyUsageOCSPSigning
ExtKeyUsageMicrosoftServerGatedCrypto
ExtKeyUsageNetscapeServerGatedCrypto
ExtKeyUsageMicrosoftCommercialCodeSigning
ExtKeyUsageMicrosoftKernelCodeSigning
)
type HostnameError ¶
type HostnameError struct {
Certificate *Certificate
Host string
}
HostnameError results when the set of authorized names doesn’t match the requested name.
(HostnameError) Error ¶
func (h HostnameError) Error() string
type InsecureAlgorithmError ¶added in go1.6
type InsecureAlgorithmError SignatureAlgorithm
An InsecureAlgorithmError indicates that the SignatureAlgorithm used to generate the signature is not secure, and the signature has been rejected.
To temporarily restore support for SHA-1 signatures, include the value “x509sha1=1” in the GODEBUG environment variable. Note that this option will be removed in a future release.
(InsecureAlgorithmError) Error ¶added in go1.6
func (e InsecureAlgorithmError) Error() string
type InvalidReason ¶
type InvalidReason int
const (
// NotAuthorizedToSign results when a certificate is signed by another
// which isn't marked as a CA certificate.
NotAuthorizedToSign InvalidReason = iota
// Expired results when a certificate has expired, based on the time
// given in the VerifyOptions.
Expired
// CANotAuthorizedForThisName results when an intermediate or root
// certificate has a name constraint which doesn't permit a DNS or
// other name (including IP address) in the leaf certificate.
CANotAuthorizedForThisName
// TooManyIntermediates results when a path length constraint is
// violated.
TooManyIntermediates
// IncompatibleUsage results when the certificate's key usage indicates
// that it may only be used for a different purpose.
IncompatibleUsage
// NameMismatch results when the subject name of a parent certificate
// does not match the issuer name in the child.
NameMismatch
// NameConstraintsWithoutSANs is a legacy error and is no longer returned.
NameConstraintsWithoutSANs
// UnconstrainedName results when a CA certificate contains permitted
// name constraints, but leaf certificate contains a name of an
// unsupported or unconstrained type.
UnconstrainedName
// TooManyConstraints results when the number of comparison operations
// needed to check a certificate exceeds the limit set by
// VerifyOptions.MaxConstraintComparisions. This limit exists to
// prevent pathological certificates can consuming excessive amounts of
// CPU time to verify.
TooManyConstraints
// CANotAuthorizedForExtKeyUsage results when an intermediate or root
// certificate does not permit a requested extended key usage.
CANotAuthorizedForExtKeyUsage
)
type KeyUsage ¶
type KeyUsage int
KeyUsage represents the set of actions that are valid for a given key. It’s a bitmap of the KeyUsage* constants.
const (
KeyUsageDigitalSignature KeyUsage = 1 << iota
KeyUsageContentCommitment
KeyUsageKeyEncipherment
KeyUsageDataEncipherment
KeyUsageKeyAgreement
KeyUsageCertSign
KeyUsageCRLSign
KeyUsageEncipherOnly
KeyUsageDecipherOnly
)
type PEMCipher ¶added in go1.1
type PEMCipher int
const (
PEMCipherDES PEMCipher
PEMCipher3DES
PEMCipherAES128
PEMCipherAES192
PEMCipherAES256
)
Possible values for the EncryptPEMBlock encryption algorithm.
type PublicKeyAlgorithm ¶
type PublicKeyAlgorithm int
const (
UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
RSA
DSA // Only supported for parsing.
ECDSA
Ed25519
)
(PublicKeyAlgorithm) String ¶added in go1.10
func (algo PublicKeyAlgorithm) String() string
type RevocationList ¶added in go1.15
type RevocationList struct {
// Raw contains the complete ASN.1 DER content of the CRL (tbsCertList,
// signatureAlgorithm, and signatureValue.)
Raw []byte
// RawTBSRevocationList contains just the tbsCertList portion of the ASN.1
// DER.
RawTBSRevocationList []byte
// RawIssuer contains the DER encoded Issuer.
RawIssuer []byte
// Issuer contains the DN of the issuing certificate.
Issuer pkix.Name
// AuthorityKeyId is used to identify the public key associated with the
// issuing certificate. It is populated from the authorityKeyIdentifier
// extension when parsing a CRL. It is ignored when creating a CRL; the
// extension is populated from the issuing certificate itself.
AuthorityKeyId []byte
Signature []byte
// SignatureAlgorithm is used to determine the signature algorithm to be
// used when signing the CRL. If 0 the default algorithm for the signing
// key will be used.
SignatureAlgorithm SignatureAlgorithm
// RevokedCertificates is used to populate the revokedCertificates
// sequence in the CRL, it may be empty. RevokedCertificates may be nil,
// in which case an empty CRL will be created.
RevokedCertificates []pkix.RevokedCertificate
// Number is used to populate the X.509 v2 cRLNumber extension in the CRL,
// which should be a monotonically increasing sequence number for a given
// CRL scope and CRL issuer. It is also populated from the cRLNumber
// extension when parsing a CRL.
Number *big.Int
// ThisUpdate is used to populate the thisUpdate field in the CRL, which
// indicates the issuance date of the CRL.
ThisUpdate time.Time
// NextUpdate is used to populate the nextUpdate field in the CRL, which
// indicates the date by which the next CRL will be issued. NextUpdate
// must be greater than ThisUpdate.
NextUpdate time.Time
// Extensions contains raw X.509 extensions. When creating a CRL,
// the Extensions field is ignored, see ExtraExtensions.
Extensions []pkix.Extension
// ExtraExtensions contains any additional extensions to add directly to
// the CRL.
ExtraExtensions []pkix.Extension
}
RevocationList contains the fields used to create an X.509 v2 Certificate Revocation list with CreateRevocationList.
func ParseRevocationList ¶added in go1.19
func ParseRevocationList(der []byte) (*RevocationList, error)
ParseRevocationList parses a X509 v2 Certificate Revocation List from the given ASN.1 DER data.
(*RevocationList) CheckSignatureFrom ¶added in go1.19
func (rl *RevocationList) CheckSignatureFrom(parent *Certificate) error
CheckSignatureFrom verifies that the signature on rl is a valid signature from issuer.
type SignatureAlgorithm ¶
type SignatureAlgorithm int
const (
UnknownSignatureAlgorithm SignatureAlgorithm = iota
MD2WithRSA // Unsupported.
MD5WithRSA // Only supported for signing, not verification.
SHA1WithRSA // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
SHA256WithRSA
SHA384WithRSA
SHA512WithRSA
DSAWithSHA1 // Unsupported.
DSAWithSHA256 // Unsupported.
ECDSAWithSHA1 // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
ECDSAWithSHA256
ECDSAWithSHA384
ECDSAWithSHA512
SHA256WithRSAPSS
SHA384WithRSAPSS
SHA512WithRSAPSS
PureEd25519
)
(SignatureAlgorithm) String ¶added in go1.6
func (algo SignatureAlgorithm) String() string
type SystemRootsError ¶added in go1.1
type SystemRootsError struct {
Err error
}
SystemRootsError results when we fail to load the system root certificates.
(SystemRootsError) Error ¶added in go1.1
func (se SystemRootsError) Error() string
(SystemRootsError) Unwrap ¶added in go1.16
func (se SystemRootsError) Unwrap() error
type UnhandledCriticalExtension ¶
type UnhandledCriticalExtension struct{}
(UnhandledCriticalExtension) Error ¶
func (h UnhandledCriticalExtension) Error() string
type UnknownAuthorityError ¶
type UnknownAuthorityError struct {
Cert *Certificate
// contains filtered or unexported fields
}
UnknownAuthorityError results when the certificate issuer is unknown
(UnknownAuthorityError) Error ¶
func (e UnknownAuthorityError) Error() string
type VerifyOptions ¶
type VerifyOptions struct {
// DNSName, if set, is checked against the leaf certificate with
// Certificate.VerifyHostname or the platform verifier.
DNSName string
// Intermediates is an optional pool of certificates that are not trust
// anchors, but can be used to form a chain from the leaf certificate to a
// root certificate.
Intermediates *CertPool
// Roots is the set of trusted root certificates the leaf certificate needs
// to chain up to. If nil, the system roots or the platform verifier are used.
Roots *CertPool
// CurrentTime is used to check the validity of all certificates in the
// chain. If zero, the current time is used.
CurrentTime time.Time
// KeyUsages specifies which Extended Key Usage values are acceptable. A
// chain is accepted if it allows any of the listed values. An empty list
// means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
KeyUsages []ExtKeyUsage
// MaxConstraintComparisions is the maximum number of comparisons to
// perform when checking a given certificate's name constraints. If
// zero, a sensible default is used. This limit prevents pathological
// certificates from consuming excessive amounts of CPU time when
// validating. It does not apply to the platform verifier.
MaxConstraintComparisions int
}
VerifyOptions contains parameters for Certificate.Verify.
2.4.21 - x509/pkix
pkix
https://pkg.go.dev/crypto/x509/pkix@go1.20.1
Package pkix contains shared, low level structures used for ASN.1 parsing and serialization of X.509 certificates, CRL and OCSP.
常量 ¶
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type AlgorithmIdentifier ¶
type AlgorithmIdentifier struct {
Algorithm asn1.ObjectIdentifier
Parameters asn1.RawValue `asn1:"optional"`
}
AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC 5280, section 4.1.1.2.
type AttributeTypeAndValue ¶
type AttributeTypeAndValue struct {
Type asn1.ObjectIdentifier
Value any
}
AttributeTypeAndValue mirrors the ASN.1 structure of the same name in RFC 5280, Section 4.1.2.4.
type AttributeTypeAndValueSET ¶added in go1.3
type AttributeTypeAndValueSET struct {
Type asn1.ObjectIdentifier
Value [][]AttributeTypeAndValue `asn1:"set"`
}
AttributeTypeAndValueSET represents a set of ASN.1 sequences of AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
typeCertificateListDEPRECATED
type Extension ¶
type Extension struct {
Id asn1.ObjectIdentifier
Critical bool `asn1:"optional"`
Value []byte
}
Extension represents the ASN.1 structure of the same name. See RFC 5280, section 4.2.
type Name ¶
type Name struct {
Country, Organization, OrganizationalUnit []string
Locality, Province []string
StreetAddress, PostalCode []string
SerialNumber, CommonName string
// Names contains all parsed attributes. When parsing distinguished names,
// this can be used to extract non-standard attributes that are not parsed
// by this package. When marshaling to RDNSequences, the Names field is
// ignored, see ExtraNames.
Names []AttributeTypeAndValue
// ExtraNames contains attributes to be copied, raw, into any marshaled
// distinguished names. Values override any attributes with the same OID.
// The ExtraNames field is not populated when parsing, see Names.
ExtraNames []AttributeTypeAndValue
}
Name represents an X.509 distinguished name. This only includes the common elements of a DN. Note that Name is only an approximation of the X.509 structure. If an accurate representation is needed, asn1.Unmarshal the raw subject or issuer as an RDNSequence.
(*Name) FillFromRDNSequence ¶
func (n *Name) FillFromRDNSequence(rdns *RDNSequence)
FillFromRDNSequence populates n from the provided RDNSequence. Multi-entry RDNs are flattened, all entries are added to the relevant n fields, and the grouping is not preserved.
(Name) String ¶added in go1.10
func (n Name) String() string
String returns the string form of n, roughly following the RFC 2253 Distinguished Names syntax.
(Name) ToRDNSequence ¶
func (n Name) ToRDNSequence() (ret RDNSequence)
ToRDNSequence converts n into a single RDNSequence. The following attributes are encoded as multi-value RDNs:
- Country
- Organization
- OrganizationalUnit
- Locality
- Province
- StreetAddress
- PostalCode
Each ExtraNames entry is encoded as an individual RDN.
type RDNSequence ¶
type RDNSequence []RelativeDistinguishedNameSET
(RDNSequence) String ¶added in go1.10
func (r RDNSequence) String() string
String returns a string representation of the sequence r, roughly following the RFC 2253 Distinguished Names syntax.
type RelativeDistinguishedNameSET ¶
type RelativeDistinguishedNameSET []AttributeTypeAndValue
type RevokedCertificate ¶
type RevokedCertificate struct {
SerialNumber *big.Int
RevocationTime time.Time
Extensions []Extension `asn1:"optional"`
}
RevokedCertificate represents the ASN.1 structure of the same name. See RFC 5280, section 5.1.
2.5 - database
2.5.1 - sql
sql
https://pkg.go.dev/database/sql@go1.20.1
sql包提供了一个围绕SQL(或类SQL)数据库的通用接口。
sql包必须与数据库驱动程序一起使用。参见https://golang.org/s/sqldrivers,获取驱动程序的列表。
不支持上下文取消的驱动程序将等到查询完成后才会返回。
关于用法的例子,请参见wiki页面https://golang.org/s/sqlwiki。
Example (OpenDBCLI)
|
|
Example (OpenDBService)
|
|
常量
This section is empty.
变量
|
|
ErrConnDone 被任何在已经返回到连接池的连接上执行的操作返回。
|
|
ErrNoRows 在 Scan 时由 QueryRow 不返回行时返回。在这种情况下,QueryRow 返回一个占位符 *Row 值,直到扫描时才会出现此错误。
|
|
ErrTxDone 被任何在已经提交或回滚的事务上执行的操作返回。
函数
func Drivers <- go1.4
|
|
Drivers函数返回已注册驱动程序名称的排序列表。
func Register
|
|
Register函数使用提供的名称使数据库驱动程序可用。如果使用相同的名称两次调用Register或者驱动程序为nil,则会引发panic。
类型
type ColumnType <- go1.8
|
|
ColumnType结构体包含列的名称和类型。
(*ColumnType) DatabaseTypeName <- go1.8
|
|
DatabaseTypeName方法返回列类型的数据库系统名称。如果返回空字符串,则不支持驱动程序类型名称。请查阅您的驱动程序文档以获取驱动程序数据类型列表。不包括长度说明符。常见类型名称包括"VARCHAR",“TEXT”,“NVARCHAR”,“DECIMAL”,“BOOL”,“INT"和"BIGINT”。
(*ColumnType) DecimalSize <- go1.8
|
|
DecimalSize方法返回十进制类型的比例和精度。如果不适用或不受支持,则为假。
(*ColumnType) Length <- go1.8
|
|
Length方法返回变量长度列类型(如文本和二进制字段类型)的列类型长度。如果类型长度不受限制,则值将是math.MaxInt64(任何数据库限制仍将适用)。如果列类型不是可变长度,例如int,或者驱动程序不支持,则为false。
(*ColumnType) Name <- go1.8
|
|
Name方法返回列的名称或别名。
(*ColumnType) Nullable <- go1.8
|
|
Nullable方法报告列是否可以为null。如果驱动程序不支持此属性,则ok将为false。
(*ColumnType) ScanType <- go1.8
|
|
ScanType方法返回适合使用Rows.Scan进行扫描的Go类型。如果驱动程序不支持此属性,则ScanType将返回空接口的类型。
type Conn <- go1.9
|
|
Conn结构体表示一个单独的数据库连接,而不是数据库连接池。除非有特定需要一个连续的单个数据库连接,否则请优先使用 DB 来运行查询。
在调用 Close方法以将连接返回到数据库池之前,Conn 必须调用 Close方法,可能与正在运行的查询同时进行。
调用 Close方法后,连接上的所有操作都将失败,并返回 ErrConnDone。
(*Conn) BeginTx <- go1.9
|
|
BeginTx方法开始一个事务。
提供的上下文会一直使用到事务提交或回滚。如果上下文被取消,sql 包将回滚事务。如果传递给 BeginTx 的上下文被取消,Tx.Commit 将返回一个错误。
提供的 TxOptions 是可选的,如果应使用默认值,则可以为 nil。如果使用了非默认的隔离级别,并且该驱动程序不支持,将返回一个错误。
(*Conn) Close <- go1.9
|
|
Close方法将连接返回到连接池。Close方法后的所有操作都将返回 ErrConnDone。Close 方法可以与其他操作并发调用,它将阻塞,直到所有其他操作完成。在调用 Close 前,先取消任何使用的上下文,然后直接调用它可能会很有用。
(*Conn) ExecContext <- go1.9
|
|
ExecContext方法执行一条查询,而不返回任何行。args 用于查询中的任何占位符参数。
ExecContext Example
|
|
(*Conn) PingContext <- go1.9
|
|
PingContext方法验证与数据库的连接是否仍然存活。
(*Conn) PrepareContext <- go1.9
|
|
PrepareContext方法为以后的查询或执行创建一个准备好的语句。可以从返回的语句中并发运行多个查询或执行。调用者在不再需要语句时必须调用语句的 Close 方法。
提供的上下文用于准备语句,而不是执行语句的上下文。
(*Conn) QueryContext <- go1.9
|
|
QueryContext方法执行一个返回行的查询,通常是SELECT。args参数用于查询中的任何占位符参数。
(*Conn) QueryRowContext <- go1.9
|
|
QueryRowContext方法执行一个预期返回最多一行的查询。QueryRowContext总是返回一个非nil值。错误会被推迟到调用Row的Scan方法时返回。如果查询没有选择任何行,则* Row的Scan将返回ErrNoRows。否则,*Row的Scan扫描第一个选择的行并丢弃其余的行。
(*Conn) Raw <- go1.13
|
|
Raw方法执行f,暴露底层驱动程序连接。driverConn不能在f之外使用。
一旦f返回且err不是driver.ErrBadConn,Conn将继续可用,直到调用Conn.Close为止。
type DB
|
|
DB结构体是表示零个或多个底层连接池的数据库句柄。它可以被多个goroutine并发使用。
sql包会自动创建和释放连接;它还维护一个空闲连接的自由池。如果数据库有每个连接状态的概念,则可以在事务(Tx)或连接(Conn)中可靠地观察到此状态。一旦调用DB.Begin,返回的Tx将绑定到单个连接。一旦在事务上调用Commit或Rollback,该事务的连接就会返回到DB的空闲连接池中。池的大小可以使用SetMaxIdleConns进行控制。
func Open
|
|
Open函数通过其数据库驱动程序名称和驱动程序特定的数据源名称打开一个数据库,通常至少包含数据库名称和连接信息。
大多数用户将通过返回*DB的特定于驱动程序的连接助手函数打开数据库。Go标准库中不包含任何数据库驱动程序。请参阅https://golang.org/s/sqldrivers以获取第三方驱动程序的列表。
Open函数可能只验证其参数而不创建到数据库的连接。要验证数据源名称是否有效,请调用Ping。
返回的DB可安全地由多个goroutine并发使用,并维护其自己的空闲连接池。因此,应该只调用一次Open函数。很少需要关闭DB。
func OpenDB <- go1.10
|
|
OpenDB函数使用Connector打开数据库,允许驱动程序绕过基于字符串的数据源名称。
大多数用户将通过特定于驱动程序的连接助手函数打开数据库,该函数返回*DB。Go标准库中不包含任何数据库驱动程序。有关第三方驱动程序的列表,请参见https://golang.org/s/sqldrivers。
OpenDB函数可能只是验证其参数而没有创建到数据库的连接。要验证数据源名称是否有效,请调用Ping。
返回的DB安全地支持多个goroutine的并发使用,并维护其自己的空闲连接池。因此,OpenDB函数应该只调用一次。很少需要关闭DB。
(*DB) Begin
|
|
Begin方法开始一个事务。默认的隔离级别取决于驱动程序。
Begin方法在内部使用context.Background;要指定上下文,请使用BeginTx方法。
(*DB) BeginTx <- go1.8
|
|
BeginTx方法开始一个事务。
提供的上下文用于直到事务提交或回滚。如果上下文被取消,则sql包将回滚事务。如果提供给BeginTx方法的上下文被取消,Tx.Commit将返回错误。
提供的TxOptions是可选的,如果应使用默认值,则可以为nil。如果使用驱动程序不支持的非默认隔离级别,则会返回错误。
BeginTx Example
|
|
(*DB) Close
|
|
Close方法关闭数据库并防止启动新查询。然后,Close方法等待在服务器上已经开始处理的所有查询完成。
很少需要关闭DB,因为DB句柄应该是长期存在的并在许多goroutine之间共享。
(*DB) Conn <- go1.9
|
|
Conn方法通过打开一个新连接或从连接池中返回一个现有连接来返回单个连接。 Conn 将阻塞直到返回连接或取消 ctx。在同一 Conn 上运行的查询将在同一个数据库会话中运行。
每个 Conn方法必须通过调用 Conn.Close 返回到数据库池中。
(*DB) Driver
|
|
Driver方法返回数据库的底层驱动程序。
(*DB) Exec
|
|
Exec方法执行一个查询,而不返回任何行。 args 是查询中任何占位符参数的参数。
Exec方法内部使用 context.Background。要指定上下文,请使用 ExecContext方法。
(*DB) ExecContext <- go1.8
|
|
ExecContext方法执行一个查询,而不返回任何行。 args 是查询中任何占位符参数的参数。
ExecContext Example
|
|
(*DB) Ping <- go1.1
|
|
Ping方法验证与数据库的连接仍然存在,必要时建立连接。
Ping方法内部使用 context.Background。要指定上下文,请使用 PingContext方法。
(*DB) PingContext <- go1.8
|
|
PingContext方法验证与数据库的连接仍然存在,必要时建立连接。
PingContext Example
|
|
(*DB) Prepare
|
|
Prepare方法创建一个准备好的语句,以便以后进行查询或执行操作。可以从返回的语句中并发运行多个查询或执行。调用者在语句不再需要时必须调用语句的 Close 方法。
Prepare方法内部使用 context.Background。要指定上下文,请使用 PrepareContext方法。
Prepare Example
|
|
(*DB) PrepareContext <- go1.8
|
|
PrepareContext方法创建一个准备好的语句,以便以后进行查询或执行操作。可以从返回的语句中并发运行多个查询或执行。调用者在语句不再需要时必须调用语句的 Close 方法。
提供的上下文用于语句的准备,而不是语句的执行。
(*DB) Query
|
|
Query方法执行返回行的查询,通常是 SELECT。args 是查询中的任何占位符参数。
Query方法内部使用 context.Background。要指定上下文,请使用 QueryContext方法。
Query Example
|
|
(*DB) QueryContext <- go1.8
|
|
QueryContext方法执行返回行的查询,通常是 SELECT。args 是查询中的任何占位符参数。
QueryContext Example
|
|
(*DB) QueryRow
|
|
QueryRow方法执行一个预期返回最多一行的查询。QueryRow方法总是返回一个非空值。错误将被延迟直到调用 Row 的 Scan 方法。如果查询未选择任何行,则 *Row 的 Scan 将返回 ErrNoRows。否则,*Row 的 Scan 扫描第一行并丢弃其余行。
QueryRow方法内部使用 context.Background。要指定上下文,请使用 QueryRowContext方法。
(*DB) QueryRowContext <- go1.8
|
|
QueryRowContext方法执行一个预期返回最多一行的查询。QueryRowContext 总是返回一个非空值。错误将被延迟直到调用 Row 的 Scan 方法。如果查询未选择任何行,则 *Row 的 Scan 将返回 ErrNoRows。否则,*Row 的 Scan 扫描第一行并丢弃其余行。
QueryRowContext Example
|
|
(*DB) SetConnMaxIdleTime <- go1.15
|
|
SetConnMaxIdleTime方法设置连接的最大空闲时间。
过期的连接可能会在重新使用之前被懒惰地关闭。
如果d <= 0,则连接不会因连接的空闲时间而关闭。
(*DB) SetConnMaxLifetime <- go1.6
|
|
SetConnMaxLifetime方法设置连接可以被重用的最长时间。
到期的连接可能会在重用之前被懒惰地关闭。
如果d <= 0,则不会因连接的年龄而关闭连接。
(*DB) SetMaxIdleConns <- go1.1
|
|
SetMaxIdleConns方法设置空闲连接池中的最大连接数。
如果MaxOpenConns大于0但小于新的MaxIdleConns,则新的MaxIdleConns将被减少以匹配MaxOpenConns限制。
如果n <= 0,则不会保留空闲连接。
默认的最大空闲连接数当前为2。这可能会在将来的版本中更改。
(*DB) SetMaxOpenConns <- go1.2
|
|
SetMaxOpenConns方法设置打开到数据库的最大连接数。
如果MaxIdleConns大于0且新的MaxOpenConns小于MaxIdleConns,则MaxIdleConns将被减少以匹配新的MaxOpenConns限制。
如果n <= 0,则没有打开连接的数量限制。默认值为0(无限制)。
(*DB) Stats <- go1.5
|
|
Stats方法返回数据库统计信息。
type DBStats <- go1.5
|
|
DBStats包含数据库统计信息。
type IsolationLevel <- go1.8
|
|
IsolationLevel是在TxOptions中使用的事务隔离级别。
|
|
各种隔离级别,驱动程序可以在BeginTx中支持。如果驱动程序不支持给定的隔离级别,则可能返回错误。
参见https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels。
(IsolationLevel) String <- go1.11
|
|
String 函数返回事务隔离级别的名称。
type NamedArg <- go1.8
|
|
NamedArg 是一个命名参数。NamedArg 值可以作为参数传递给 Query 或 Exec 并绑定到 SQL 语句中相应的命名参数。
为了更简洁地创建 NamedArg 值,请参考 Named 函数。
func Named <- go1.8
|
|
Named 函数提供了一种更简洁的方式来创建 NamedArg 值。
Example usage:
使用示例:
|
|
type NullBool
|
|
NullBool结构体表示可能为空的 bool 值。NullBool 实现了 Scanner 接口,因此它可以用作扫描目标,类似于 NullString。
(*NullBool) Scan
|
|
Scan方法实现了 Scanner 接口。
(NullBool) Value
|
|
Value方法实现了 driver Valuer 接口。
type NullByte <- go1.17
|
|
NullByte结构体表示一个可能为空的 byte。NullByte 实现了 Scanner 接口,因此它可以像 NullString 一样用作扫描目标。
(*NullByte) Scan <- go1.17
|
|
Scan方法实现了 Scanner 接口。
(NullByte) Value <- go1.17
|
|
Value方法实现了 driver Valuer 接口。
type NullFloat64
|
|
NullFloat64结构体表示一个可能为空的 float64。NullFloat64 实现了 Scanner 接口,因此它可以像 NullString 一样用作扫描目标。
(*NullFloat64) Scan
|
|
Scan方法实现了 Scanner 接口。
(NullFloat64) Value
|
|
Value方法实现了 driver Valuer 接口。
type NullInt16 <- go1.17
|
|
NullInt16结构体表示可能为null的int16。NullInt16实现Scanner接口,因此它可以用作扫描目标,类似于NullString。
(*NullInt16) Scan <- go1.17
|
|
Scan方法实现Scanner接口。
(NullInt16) Value <- go1.17
|
|
Value方法实现driver Valuer接口。
type NullInt32 <- go1.13
|
|
NullInt32结构体表示可能为null的int32。NullInt32实现Scanner接口,因此它可以用作扫描目标,类似于NullString。
(*NullInt32) Scan <- go1.13
|
|
Scan方法实现Scanner接口。
(NullInt32) Value <- go1.13
|
|
Value方法实现driver Valuer接口。
type NullInt64
|
|
NullInt64结构体表示可能为null的int64。NullInt64实现Scanner接口,因此它可以用作扫描目标,类似于NullString。
(*NullInt64) Scan
|
|
Scan方法实现Scanner接口。
(NullInt64) Value
|
|
Value方法实现driver Valuer接口。
type NullString
|
|
NullString结构体表示可能为 null 的字符串。NullString 实现了 Scanner 接口,因此可以用作扫描目标:
|
|
(*NullString) Scan
|
|
Scan方法实现了 Scanner 接口。
(NullString) Value
|
|
Value方法实现了 driver Valuer 接口。
type NullTime <- go1.13
|
|
NullTime结构体表示可能为 null 的 time.Time。NullTime 实现了 Scanner 接口,因此可以用作扫描目标,类似于 NullString。
(*NullTime) Scan <- go1.13
|
|
Scan方法实现了 Scanner 接口。
(NullTime) Value <- go1.13
|
|
Value方法实现了 driver Valuer 接口。
type Out <- go1.9
|
|
Out结构体可用于从存储过程中检索 OUTPUT 值参数。
并非所有驱动程序和数据库都支持 OUTPUT 值参数。
使用示例:
|
|
type RawBytes
|
|
RawBytes 是一个字节切片,它持有数据库本身拥有的内存引用。将 RawBytes扫描后,该切片仅在下一次调用 Next方法、Scan方法或 Close方法之前有效。
type Result
|
|
Result 是对执行的 SQL 命令的摘要。
type Row
|
|
Row结构体是调用 QueryRow方法选择单行时的结果。
(*Row) Err <- go1.15
|
|
Err方法提供了一种方法,使封装的包在不调用 Scan方法的情况下检查查询错误。如果在运行查询时遇到错误,Err 返回错误(如果有)。如果此错误不是 nil,则还将从 Scan 返回此错误。
(*Row) Scan
|
|
Scan方法将匹配的行中的列复制到 dest 指向的值中。有关详细信息,请参见 Rows.Scan 的文档。如果有多行与查询匹配,则 Scan方法使用第一行并且忽略其余的行。如果没有行与查询匹配,则 Scan方法返回 ErrNoRows。
type Rows
|
|
Rowsjgt是查询的结果。它的游标在结果集的第一行之前。使用 Next方法来从一行移到另一行。
Rows Example
|
|
(*Rows) Close
|
|
Close方法方法关闭 Rows,防止进一步枚举。如果调用 Next 并且返回 false,并且没有其他结果集,则 Rows 将自动关闭,并且检查 Err 的结果就足够了。Close方法是幂等的,不会影响 Err 的结果。
(*Rows) ColumnTypes <- go1.8
|
|
ColumnTypes方法返回列信息,例如列类型、长度和可空性。某些信息可能不适用于某些驱动程序。
(*Rows) Columns
|
|
Columns方法返回列名。如果行已关闭,则 Columns方法返回错误。
(*Rows) Err
|
|
Err方法返回迭代过程中遇到的错误(如果有)。Err方法可以在显式或隐式 Close 后调用。
(*Rows) Next
|
|
Next方法准备下一个结果行以供 Scan 方法读取。它返回 true 表示成功,false 表示没有下一个结果行或准备它时发生错误。应该使用 Err 来区分这两种情况。
每次调用 Scan方法,即使是第一次调用,也必须先调用 Next方法。
(*Rows) NextResultSet <- go1.8
|
|
NextResultSet方法准备下一个结果集以供读取。它返回 true 表示还有其他结果集,或者 false 表示没有其他结果集,或者无法提前到其结果集。应该使用 Err 方法来区分这两种情况。
在调用 NextResultSet方法后,应始终在扫描之前调用 Next 方法。如果还有其他结果集,则它们可能没有结果集中的行。
(*Rows) Scan
|
|
Scan方法将当前行的列复制到 dest 指向的值中。dest 中的值数量必须与 Rows 中的列数相同。
Scan方法将从数据库中读取的列转换为 sql 包提供的以下常见 Go 类型和特殊类型:
*string
*[]byte
*int, *int8, *int16, *int32, *int64
*uint, *uint8, *uint16, *uint32, *uint64
*bool
*float32, *float64
*interface{}
*RawBytes
*Rows (cursor value)
any type implementing Scanner (see Scanner docs)
实现 Scanner 接口的任何类型(请参见 Scanner 文档) 在最简单的情况下,如果源列的值类型是整数、布尔或字符串类型 T,而 dest 的类型是 *T,则 Scan 只需通过指针分配值。
Scan 还可以在字符串和数字类型之间进行转换,只要不会丢失信息即可。虽然 Scan 将从数值数据库列中读取的所有数字字符串化为 *string,但会检查是否存在数字类型的扫描溢出。例如,值为 300 的 float64 或值为 “300” 的字符串可以扫描到 uint16,但不能扫描到 uint8,尽管 float64(255) 或 “255” 可以扫描到 uint8。有一个例外,即某些 float64 数字扫描为字符串时可能会丢失信息。通常,将浮点列扫描到 *float64 中。
如果 dest 参数的类型为 *[]byte,则 Scan 会在该参数中保存相应数据的副本。该副本由调用方拥有,可以进行修改并无限期保留。可以通过使用类型 *RawBytes 的参数来避免复制;请参阅 RawBytes 的文档以了解其使用限制。
如果一个参数的类型是 *interface{},Scan 会复制由底层驱动程序提供的值,而不进行转换。从类型 []byte 到 *interface{} 扫描时,会复制切片并且调用方拥有结果。
类型 time.Time 的源值可以扫描到类型 *time.Time、*interface{}、*string 或 *[]byte 的值中。转换为后两者时,使用 time.RFC3339Nano。
布尔类型的源值可以扫描到类型 *bool、*interface{}、string、[]byte 或 *RawBytes 中。
对于扫描到 *bool,源可以是 true、false、1、0 或可由 strconv.ParseBool 解析的字符串输入。
Scan 还可以将查询返回的游标(例如 “select cursor(select * from my_table) from dual”)转换为 *Rows 值,该值本身可以进行扫描。如果父选择查询关闭了任何游标 *Rows,则父选择查询将关闭它。
如果实现 Scanner 接口的第一个参数返回错误,则该错误将包装在返回的错误中。
type Scanner
|
|
Scanner是由Scan使用的接口。
type Stmt
|
|
Stmt结构体是一个预处理语句。Stmt对于多个goroutine并发使用是安全的。
如果在Tx或Conn上准备了Stmt,则将永远绑定到单个底层连接。 如果Tx或Conn关闭,则Stmt将变得无法使用,所有操作都将返回错误。 如果在DB上准备了Stmt,则在DB的生命周期内将保持可用。当Stmt需要在新的底层连接上执行时, 它将自动在新连接上准备自己。
Stmt Example
|
|
(*Stmt) Close
|
|
Close方法关闭该语句。
(*Stmt) Exec
|
|
Exec方法使用给定的参数执行预处理语句,并返回概括语句效果的Result。
Exec方法在内部使用context.Background。要指定上下文,请使用ExecContext方法。
(*Stmt) ExecContext <- go1.8
|
|
ExecContext方法使用给定的参数执行预处理语句,并返回概括语句效果的Result。
(*Stmt) Query
|
|
Query方法使用给定的参数执行预处理查询语句,并将查询结果作为*Rows返回。
Query方法在内部使用context.Background。要指定上下文,请使用QueryContext方法。
(*Stmt) QueryContext <- go1.8
|
|
QueryContext方法使用给定的参数执行预处理查询语句,并将查询结果作为*Rows返回。
(*Stmt) QueryRow
|
|
QueryRow方法使用给定的参数执行预处理的查询语句。如果在执行语句期间出现错误,则通过对返回的*Row调用Scan返回该错误,该*Row始终非零。如果查询未选择任何行,则*Row的Scan将返回ErrNoRows。否则,*Row的Scan将扫描第一个选定的行并丢弃其余行。
使用示例:
|
|
QueryRow方法在内部使用context.Background;要指定上下文,请使用QueryRowContext方法。
(*Stmt) QueryRowContext <- go1.8
|
|
QueryRowContext方法使用给定的参数执行预处理的查询语句。如果在执行语句期间出现错误,则通过对返回的*Row调用Scan返回该错误,该*Row始终非零。如果查询未选择任何行,则*Row的Scan将返回ErrNoRows。否则,*Row的Scan将扫描第一个选定的行并丢弃其余行。
QueryRowContext Example
|
|
type Tx
|
|
Tx结构体是数据库事务中的一个过程。
事务必须以Commit方法或Rollback方法的调用结束。
在调用Commit方法或Rollback方法之后,所有事务上的操作都会失败并返回ErrTxDone。
通过调用事务的Prepare方法或Stmt方法方法准备的语句将在调用Commit方法或Rollback方法时关闭。
(*Tx) Commit
|
|
Commit方法提交事务。
(*Tx) Exec
|
|
Exec方法执行不返回行的查询。例如:INSERT和UPDATE。
Exec方法在内部使用context.Background;要指定上下文,请使用ExecContext方法。
(*Tx) ExecContext <- go1.8
|
|
ExecContext方法执行不返回行的查询。例如:INSERT和UPDATE。
ExecContext Example
|
|
(*Tx) Prepare
|
|
Prepare方法创建一个准备好的语句以在事务中使用。
返回的语句在事务中运行,并将在事务提交或回滚时关闭。
要在此事务上使用现有的准备好的语句,请参见Tx.Stmt。
Prepare方法在内部使用context.Background; 要指定上下文,请使用PrepareContext。
Prepare Example
|
|
(*Tx) PrepareContext <- go1.8
|
|
PrepareContext方法创建一个准备好的语句以在事务中使用。
返回的语句在事务中运行,并将在事务提交或回滚时关闭。
要在此事务上使用现有的准备好的语句,请参见Tx.Stmt。
提供的上下文将用于准备上下文,而不是用于执行返回的语句。返回的语句将在事务上下文中运行。
(*Tx) Query
|
|
Query方法执行返回行的查询,通常是 SELECT。
Query方法在内部使用context.Background;要指定上下文,请使用QueryContext方法。
(*Tx) QueryContext <- go1.8
|
|
QueryContext方法执行返回行的查询,通常是 SELECT。
(*Tx) QueryRow
|
|
QueryRow方法执行预期最多返回一行的查询。QueryRow方法总是返回一个非空值。错误被延迟到调用 Row 的 Scan 方法时才会返回。如果查询未选择行,则 *Row 的 Scan 将返回 ErrNoRows。否则,*Row 的 Scan 扫描第一个选择的行并丢弃其余的行。
QueryRow方法在内部使用context.Background;要指定上下文,请使用QueryRowContext。
(*Tx) QueryRowContext <- go1.8
|
|
QueryRowContext方法执行预期最多返回一行的查询。QueryRowContext方法总是返回一个非空值。错误被延迟到调用 Row 的 Scan 方法时才会返回。如果查询未选择行,则 *Row 的 Scan 将返回 ErrNoRows。否则,*Row 的 Scan 扫描第一个选择的行并丢弃其余的行。
(*Tx) Rollback
|
|
Rollback方法中止事务。
Rollback Example
|
|
(*Tx) Stmt
|
|
Stmt方法从现有语句返回一个事务特定的准备好的语句。
示例:
|
|
返回的语句在事务中运行,并在事务提交或回滚后关闭。
Stmt在内部使用context.Background;要指定上下文,请使用StmtContext。
(*Tx) StmtContext <- go1.8
|
|
StmtContext方法从现有语句返回一个事务特定的准备语句。
Example:
|
|
提供的上下文用于准备语句,而不是执行语句。
返回的语句在事务中运行,并在事务提交或回滚后关闭。
type TxOptions <- go1.8
|
|
TxOptions保存在DB.BeginTx中使用的事务选项。
2.5.2 - sql/driver
driver
https://pkg.go.dev/database/sql/driver@go1.20.1
driver包定义了数据库驱动需要实现的接口,供sql包使用。
大多数代码应该使用 sql 包。
驱动程序接口随着时间的推移而发展。驱动程序应该实现 Connector 和 DriverContext 接口。Connector.Connect 和 Driver.Open 方法不应返回 ErrBadConn。如果连接已经处于无效状态(例如已关闭),则 ErrBadConn 只能从 Validator、SessionResetter 或查询方法中返回。
所有 Conn 实现都应该实现以下接口:Pinger、SessionResetter 和 Validator。
如果支持命名参数或上下文,则驱动程序的 Conn 应实现:ExecerContext、QueryerContext、ConnPrepareContext 和 ConnBeginTx。
为支持自定义数据类型,实现 NamedValueChecker。NamedValueChecker 还允许查询通过返回 ErrRemoveArgument 接受每个查询选项作为参数。
如果支持多个结果集,则 Rows 应实现 RowsNextResultSet。如果驱动程序知道返回结果中存在的类型,它应该实现以下接口:RowsColumnTypeScanType、RowsColumnTypeDatabaseTypeName、RowsColumnTypeLength、RowsColumnTypeNullable 和 RowsColumnTypePrecisionScale。给定行值也可以返回 Rows 类型,它可能表示数据库游标值。
在将连接归还给连接池之前,如果实现了 IsValid,则会调用 IsValid。在将连接用于另一个查询之前,如果实现了 ResetSession,则会调用 ResetSession。如果连接从未返回给连接池,而是立即重用,则在重用之前调用 ResetSession,但不调用 IsValid。
常量
This section is empty.
变量
|
|
Bool是ValueConverter,用于将输入值转换为布尔值。
转换规则如下:
- 布尔值不变
- 对于整数类型,1为真,0为假,其他整数为错误
- 对于字符串和[]byte,与strconv.ParseBool相同的规则
- 所有其他类型都是一个错误
|
|
DefaultParameterConverter是ValueConverter的默认实现,当Stmt未实现ColumnConverter时使用。
DefaultParameterConverter如果IsValue(arg)则直接返回其参数。否则,如果参数实现了Valuer,则使用其Value方法返回一个Value。作为后备,提供的参数的基础类型用于将其转换为Value:基础整数类型转换为int64,浮点数转换为float64,bool,string和[]byte转换为自身。如果参数是nil指针,则ConvertValue返回nil Value。如果参数是非nil指针,则对其进行取消引用,并递归调用ConvertValue。其他类型是一个错误。
|
|
如果驱动程序处于错误状态(例如服务器早期关闭连接),则驱动程序应返回ErrBadConn,以向sql包发信号。sql包应该在新连接上重试。
为了防止重复操作,如果数据库服务器可能执行操作,则不应返回ErrBadConn。即使服务器发送错误,您也不应返回ErrBadConn。
使用errors.Is检查错误。一个错误可能包装ErrBadConn或实现Is(error) bool方法。
|
|
NamedValueChecker可能会返回ErrRemoveArgument,以指示sql包不将参数传递给驱动程序查询接口。在接受特定于查询的选项或不是SQL查询参数的结构时返回。
|
|
某些可选接口的方法可能返回ErrSkip,以表示在运行时快速路径不可用,sql包应继续,就像未实现可选接口一样。仅在明确文档中记录了ErrSkip。
|
|
Int32是ValueConverter,用于将输入值转换为int64,并考虑int32值的限制。
|
|
ResultNoRows是预定义结果,驱动程序在DDL命令(如CREATE TABLE)成功时返回。它对于LastInsertId和RowsAffected都返回错误。
|
|
String是ValueConverter,用于将其输入转换为字符串。如果该值已经是字符串或[]byte,则不变。如果值是其他类型,则使用fmt.Sprintf("%v",v)进行字符串转换。
函数
func IsScanValue
|
|
IsScanValue函数等价于 IsValue。它存在是为了兼容性。
func IsValue
|
|
IsValue函数报告v是否为有效的 Value 参数类型。
类型
type Conn
|
|
Conn 是到数据库的连接。它不会被多个goroutine同时使用。
Conn 被认为是有状态的。
type ConnBeginTx <- go1.8
|
|
ConnBeginTx 使用上下文和 TxOptions 增强了 Conn 接口。
type ConnPrepareContext <- go1.8
|
|
ConnPrepareContext 通过上下文增强 Conn 接口。
type Connector <- go1.10
|
|
Connector 表示一个具有固定配置的驱动程序,并可以创建任意数量的等效 Conns 供多个 goroutine 使用。
可以将 Connector 传递给 sql.OpenDB,以允许驱动程序实现其自己的 sql.DB 构造函数,或者由 DriverContext 的 OpenConnector 方法返回,以允许驱动程序访问上下文并避免重复解析驱动程序配置。
如果 Connector 实现了 io.Closer,则 sql 包的 DB.Close 方法将调用 Close 并返回错误(如果有)。
type Driver
|
|
Driver 是必须由数据库驱动程序实现的接口。
数据库驱动程序可以实现 DriverContext,以便访问上下文并仅解析一次名称以获得连接池,而不是每个连接都解析一次。
type DriverContext <- go1.10
|
|
如果 Driver 实现了 DriverContext 接口,那么 sql.DB 将调用 OpenConnector 来获取 Connector,并调用该 Connector 的 Connect 方法来获取每个所需的连接,而不是为每个连接调用 Driver 的 Open 方法。这个两步的过程允许驱动程序只解析一次名称,并且提供对每个 Conn 的上下文访问。
type ExecerContext <- go1.8
|
|
ExecerContext 是一个可选接口,可以由 Conn 实现。
如果 Conn 没有实现 ExecerContext,则 sql 包的 DB.Exec 将退回到 Execer;如果 Conn 也没有实现 Execer,则 DB.Exec 将首先准备查询,执行语句,然后关闭语句。
ExecContext 可能返回 ErrSkip。
ExecContext 必须遵守上下文超时,并在上下文取消时返回。
type IsolationLevel <- go1.8
|
|
IsolationLevel 是存储在 TxOptions 中的事务隔离级别。
这个类型应该被认为与 sql.IsolationLevel 相同,以及其上定义的任何值。
type NamedValue <- go1.8
|
|
NamedValue 持有值的名称和值。
type NamedValueChecker <- go1.9
|
|
NamedValueChecker 可以由 Conn 或 Stmt 可选实现。它为驱动程序提供了更多的控制权,以处理超出默认的 Value 类型允许的 Go 和数据库类型。
sql包会按照以下顺序检查值检查器,并在找到第一个匹配项时停止:Stmt.NamedValueChecker、Conn.NamedValueChecker、Stmt.ColumnConverter和DefaultParameterConverter。
如果CheckNamedValue返回ErrRemoveArgument,则NamedValue不会包含在最终查询参数中。这可用于向查询本身传递特殊选项。
如果返回ErrSkip,则对于该参数将使用列转换器错误检查路径。驱动程序可能会在耗尽其自己的特殊情况后返回ErrSkip。
type NotNull
|
|
NotNull结构体是一种类型,通过禁止nil值但否则委托给另一个ValueConverter来实现ValueConverter。
(NotNull) ConvertValue
|
|
type Null
|
|
Null结构体是一种类型,通过允许nil值但否则委托给另一个ValueConverter来实现ValueConverter。
(Null) ConvertValue
|
|
type Pinger <- go1.8
|
|
Pinger是Conn可能实现的一个可选接口。
如果Conn未实现Pinger,则sql包的DB.Ping和DB.PingContext将检查是否至少有一个Conn可用。
如果Conn.Ping返回ErrBadConn,则DB.Ping和DB.PingContext将从池中删除Conn。
type QueryerContext <- go1.8
|
|
QueryerContext是Conn可能实现的一个可选接口。
如果Conn未实现QueryerContext,则sql包的DB.Query将回退到Queryer;如果Conn也未实现Queryer,则DB.Query将首先准备查询,执行语句,然后关闭语句。
QueryContext可能会返回ErrSkip。
QueryContext必须遵守上下文超时并在取消上下文时返回。
type Result
|
|
Result接口表示一个查询操作的结果。
type Rows
|
|
Rows接口是一个已执行查询的结果集迭代器。
type RowsAffected
|
|
RowsAffected 表示执行 INSERT 或 UPDATE 操作所影响的行数,实现了 Result 接口。
(RowsAffected) LastInsertId
|
|
(RowsAffected) RowsAffected
|
|
type RowsColumnTypeDatabaseTypeName <- go1.8
|
|
RowsColumnTypeDatabaseTypeName接口可以被 Rows 实现。它应该返回数据库系统类型名称,但不包括长度信息。类型名称应大写。以下是各种类型的返回示例:“VARCHAR”、“NVARCHAR”、“VARCHAR2”、“CHAR”、“TEXT”、“DECIMAL”、“SMALLINT”、“INT”、“BIGINT”、“BOOL”、"[]BIGINT"、“JSONB”、“XML”、“TIMESTAMP”。
type RowsColumnTypeLength <- go1.8
|
|
RowsColumnTypeLength接口可以被 Rows 实现。如果列是变长类型,则它应返回列类型的长度。如果列不是变长类型,则应该返回 false。如果长度除系统限制外不受限制,则应返回 math.MaxInt64。以下是各种类型的返回示例:
TEXT (math.MaxInt64, true)
varchar(10) (10, true)
nvarchar(10) (10, true)
decimal (0, false)
int (0, false)
bytea(30) (30, true)
type RowsColumnTypeNullable <- go1.8
|
|
RowsColumnTypeNullable接口是由Rows实现的可选接口。如果已知该列可以为null,则可为空值应为true;如果已知该列不可为空,则为空值为false。如果列的可空性未知,则ok应为false。
type RowsColumnTypePrecisionScale <- go1.8
|
|
RowsColumnTypePrecisionScale接口是由Rows实现的可选接口。它应返回十进制类型的精度和刻度。如果不适用,则应将ok设置为false。以下是各种类型的返回值示例:
decimal(38, 4) (38, 4, true)
int (0, 0, false)
decimal (math.MaxInt64, math.MaxInt64, true)
type RowsColumnTypeScanType <- go1.8
|
|
RowsColumnTypeScanType接口是由Rows实现的可选接口。它应返回可以用于扫描类型的值类型。例如,对于数据库列类型"bigint",这应返回"reflect.TypeOf(int64(0))"。
type RowsNextResultSet <- go1.8
|
|
RowsNextResultSet接口通过提供一种信号方式来扩展Rows接口,以使驱动程序前进到下一个结果集。
type SessionResetter <- go1.10
|
|
SessionResetter接口可以由Conn实现,以允许驱动程序重置与连接相关的会话状态并发出坏连接信号。
type Stmt
|
|
Stmt接口是预处理语句。它绑定到Conn,不能被多个goroutine同时使用。
type StmtExecContext <- go1.8
|
|
StmtExecContext接口通过提供带有上下文的Exec来增强Stmt接口。
type StmtQueryContext <- go1.8
|
|
StmtQueryContext接口通过提供带有上下文的Query来增强Stmt接口。
type Tx
|
|
Tx 是事务。
type TxOptions <- go1.8
|
|
TxOptions结构体存储事务的选项。
此类型应被认为与 sql.TxOptions 相同。
type Validator <- go1.15
|
|
Validator接口可以被 Conn 实现,以允许驱动程序表明连接是否有效或是否应丢弃。
如果实现了 Validator,则驱动程序可能会从查询中返回基础错误,即使连接应该由连接池丢弃。
type Value
|
|
Value类型是驱动程序必须能够处理的值。它可以是 nil、由数据库驱动程序的 NamedValueChecker 接口处理的类型,或是以下类型的实例
int64
float64
bool
[]byte
string
time.Time
如果驱动程序支持游标,则返回的 Value 还可以在此包中实现 Rows 接口。例如,当用户选择类似于"select cursor(select * from my_table) from dual"这样的光标时。如果从选择中的 Rows 被关闭,则光标 Rows 也将被关闭。
type ValueConverter
|
|
ValueConverter接口是提供 ConvertValue 方法的接口。
驱动程序包提供了 ValueConverter 的各种实现,以提供驱动程序之间的一致的转换实现。ValueConverter 有以下几个用途:
- 将 sql 包提供的 Value 类型转换为数据库表的特定列类型,并确保其适合,例如确保特定 int64 适合于表的 uint16 列。
- 将从数据库中给出的值转换为驱动程序 Value 类型之一。
- 由 sql 包,在扫描中将驱动程序的 Value 类型转换为用户的类型。
type Valuer
|
|
Valuer接口是提供 Value 方法的接口。
实现 Valuer 接口的类型能够将自身转换为驱动程序 Value。
2.6 - debug
2.6.1 - buildinfo
buildinfo
https://pkg.go.dev/debug/buildinfo@go1.20.1
Package buildinfo provides access to information embedded in a Go binary about how it was built. This includes the Go toolchain version, and the set of modules used (for binaries built in module mode).
包buildinfo提供了对嵌入Go二进制文件中的信息的访问,了解它是如何构建的。这包括Go工具链的版本,以及所使用的模块集(对于以模块模式构建的二进制文件)。
Build information is available for the currently running binary in runtime/debug.ReadBuildInfo.
在runtime/debug.ReadBuildInfo中,当前运行的二进制文件可以获得构建信息。
常量
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type BuildInfo
|
|
Type alias for build info. We cannot move the types here, since runtime/debug would need to import this package, which would make it a much larger dependency.
构建信息的类型别名。我们不能把类型移到这里,因为 runtime/debug 需要导入这个包,这将使它成为一个更大的依赖关系。
func Read
|
|
Read returns build information embedded in a Go binary file accessed through the given ReaderAt. Most information is only available for binaries built with module support.
Read 返回嵌入在通过给定的ReaderAt访问的Go二进制文件中的构建信息。大多数信息只适用于有模块支持的二进制文件。
func ReadFile
|
|
ReadFile returns build information embedded in a Go binary file at the given path. Most information is only available for binaries built with module support.
ReadFile返回嵌入在给定路径的Go二进制文件中的构建信息。大多数信息只适用于有模块支持的二进制文件。
2.6.2 - dwarf
dwarf
https://pkg.go.dev/debug/dwarf@go1.20.1
Package dwarf provides access to DWARF debugging information loaded from executable files, as defined in the DWARF 2.0 Standard at http://dwarfstd.org/doc/dwarf-2.0.0.pdf.
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, only basic validation is done when parsing object files. As such, care should be taken when parsing untrusted inputs, as parsing malformed files may consume significant resources, or cause panics.
常量
This section is empty.
变量
|
|
ErrUnknownPC is the error returned by LineReader.ScanPC when the seek PC is not covered by any entry in the line table.
函数
This section is empty.
类型
type AddrType
|
|
An AddrType represents a machine address type.
type ArrayType
|
|
An ArrayType represents a fixed size array type.
(*ArrayType) Size
|
|
(*ArrayType) String
|
|
type Attr
|
|
An Attr identifies the attribute type in a DWARF Entry’s Field.
|
|
(Attr) GoString
|
|
(Attr) String
|
|
type BasicType
|
|
A BasicType holds fields common to all basic types.
See the documentation for StructField for more info on the interpretation of the BitSize/BitOffset/DataBitOffset fields.
(*BasicType) Basic
|
|
(*BasicType) String
|
|
type BoolType
|
|
A BoolType represents a boolean type.
type CharType
|
|
A CharType represents a signed character type.
type Class <- go1.5
|
|
A Class is the DWARF 4 class of an attribute value.
In general, a given attribute’s value may take on one of several possible classes defined by DWARF, each of which leads to a slightly different interpretation of the attribute.
DWARF version 4 distinguishes attribute value classes more finely than previous versions of DWARF. The reader will disambiguate coarser classes from earlier versions of DWARF into the appropriate DWARF 4 class. For example, DWARF 2 uses “constant” for constants as well as all types of section offsets, but the reader will canonicalize attributes in DWARF 2 files that refer to section offsets to one of the Class*Ptr classes, even though these classes were only defined in DWARF 3.
|
|
(Class) GoString <- go1.5
|
|
(Class) String <- go1.5
|
|
type CommonType
|
|
A CommonType holds fields common to multiple types. If a field is not known or not applicable for a given type, the zero value is used.
(*CommonType) Common
|
|
(*CommonType) Size
|
|
type ComplexType
|
|
A ComplexType represents a complex floating point type.
type Data
|
|
Data represents the DWARF debugging information loaded from an executable file (for example, an ELF or Mach-O executable).
func New
|
|
New returns a new Data object initialized from the given parameters. Rather than calling this function directly, clients should typically use the DWARF method of the File type of the appropriate package debug/elf, debug/macho, or debug/pe.
The []byte arguments are the data from the corresponding debug section in the object file; for example, for an ELF object, abbrev is the contents of the “.debug_abbrev” section.
(*Data) AddSection <- go1.14
|
|
AddSection adds another DWARF section by name. The name should be a DWARF section name such as “.debug_addr”, “.debug_str_offsets”, and so forth. This approach is used for new DWARF sections added in DWARF 5 and later.
(*Data) AddTypes <- go1.3
|
|
AddTypes will add one .debug_types section to the DWARF data. A typical object with DWARF version 4 debug info will have multiple .debug_types sections. The name is used for error reporting only, and serves to distinguish one .debug_types section from another.
(*Data) LineReader <- go1.5
|
|
LineReader returns a new reader for the line table of compilation unit cu, which must be an Entry with tag TagCompileUnit.
If this compilation unit has no line table, it returns nil, nil.
(*Data) Ranges <- go1.7
|
|
Ranges returns the PC ranges covered by e, a slice of [low,high) pairs. Only some entry types, such as TagCompileUnit or TagSubprogram, have PC ranges; for others, this will return nil with no error.
(*Data) Reader
|
|
Reader returns a new Reader for Data. The reader is positioned at byte offset 0 in the DWARF “info” section.
(*Data) Type
|
|
Type reads the type at off in the DWARF “info” section.
type DecodeError
|
|
(DecodeError) Error
|
|
type DotDotDotType
|
|
A DotDotDotType represents the variadic … function parameter.
(*DotDotDotType) String
|
|
type Entry
|
|
An entry is a sequence of attribute/value pairs.
(*Entry) AttrField <- go1.5
|
|
AttrField returns the Field associated with attribute Attr in Entry, or nil if there is no such attribute.
(*Entry) Val
|
|
Val returns the value associated with attribute Attr in Entry, or nil if there is no such attribute.
A common idiom is to merge the check for nil return with the check that the value has the expected dynamic type, as in:
v, ok := e.Val(AttrSibling).(int64)
type EnumType
|
|
An EnumType represents an enumerated type. The only indication of its native integer type is its ByteSize (inside CommonType).
(*EnumType) String
|
|
type EnumValue
|
|
An EnumValue represents a single enumeration value.
type Field
|
|
A Field is a single attribute/value pair in an Entry.
A value can be one of several “attribute classes” defined by DWARF. The Go types corresponding to each class are:
DWARF class Go type Class
----------- ------- -----
address uint64 ClassAddress
block []byte ClassBlock
constant int64 ClassConstant
flag bool ClassFlag
reference
to info dwarf.Offset ClassReference
to type unit uint64 ClassReferenceSig
string string ClassString
exprloc []byte ClassExprLoc
lineptr int64 ClassLinePtr
loclistptr int64 ClassLocListPtr
macptr int64 ClassMacPtr
rangelistptr int64 ClassRangeListPtr
For unrecognized or vendor-defined attributes, Class may be ClassUnknown.
type FloatType
|
|
A FloatType represents a floating point type.
type FuncType
|
|
A FuncType represents a function type.
(*FuncType) String
|
|
type IntType
|
|
An IntType represents a signed integer type.
type LineEntry <- go1.5
|
|
A LineEntry is a row in a DWARF line table.
type LineFile <- go1.5
|
|
A LineFile is a source file referenced by a DWARF line table entry.
type LineReader <- go1.5
|
|
A LineReader reads a sequence of LineEntry structures from a DWARF “line” section for a single compilation unit. LineEntries occur in order of increasing PC and each LineEntry gives metadata for the instructions from that LineEntry’s PC to just before the next LineEntry’s PC. The last entry will have its EndSequence field set.
(*LineReader) Files <- go1.14
|
|
Files returns the file name table of this compilation unit as of the current position in the line table. The file name table may be referenced from attributes in this compilation unit such as AttrDeclFile.
Entry 0 is always nil, since file index 0 represents “no file”.
The file name table of a compilation unit is not fixed. Files returns the file table as of the current position in the line table. This may contain more entries than the file table at an earlier position in the line table, though existing entries never change.
(*LineReader) Next <- go1.5
|
|
Next sets *entry to the next row in this line table and moves to the next row. If there are no more entries and the line table is properly terminated, it returns io.EOF.
Rows are always in order of increasing entry.Address, but entry.Line may go forward or backward.
(*LineReader) Reset <- go1.5
|
|
Reset repositions the line table reader at the beginning of the line table.
(*LineReader) Seek <- go1.5
|
|
Seek restores the line table reader to a position returned by Tell.
The argument pos must have been returned by a call to Tell on this line table.
(*LineReader) SeekPC <- go1.5
|
|
SeekPC sets *entry to the LineEntry that includes pc and positions the reader on the next entry in the line table. If necessary, this will seek backwards to find pc.
If pc is not covered by any entry in this line table, SeekPC returns ErrUnknownPC. In this case, *entry and the final seek position are unspecified.
Note that DWARF line tables only permit sequential, forward scans. Hence, in the worst case, this takes time linear in the size of the line table. If the caller wishes to do repeated fast PC lookups, it should build an appropriate index of the line table.
(*LineReader) Tell <- go1.5
|
|
Tell returns the current position in the line table.
type LineReaderPos <- go1.5
|
|
A LineReaderPos represents a position in a line table.
type Offset
|
|
An Offset represents the location of an Entry within the DWARF info. (See Reader.Seek.)
type PtrType
|
|
A PtrType represents a pointer type.
(*PtrType) String
|
|
type QualType
|
|
A QualType represents a type that has the C/C++ “const”, “restrict”, or “volatile” qualifier.
(*QualType) Size
|
|
(*QualType) String
|
|
type Reader
|
|
A Reader allows reading Entry structures from a DWARF “info” section. The Entry structures are arranged in a tree. The Reader’s Next function return successive entries from a pre-order traversal of the tree. If an entry has children, its Children field will be true, and the children follow, terminated by an Entry with Tag 0.
(*Reader) AddressSize <- go1.5
|
|
AddressSize returns the size in bytes of addresses in the current compilation unit.
(*Reader) ByteOrder <- go1.14
|
|
ByteOrder returns the byte order in the current compilation unit.
(*Reader) Next
|
|
Next reads the next entry from the encoded entry stream. It returns nil, nil when it reaches the end of the section. It returns an error if the current offset is invalid or the data at the offset cannot be decoded as a valid Entry.
(*Reader) Seek
|
|
Seek positions the Reader at offset off in the encoded entry stream. Offset 0 can be used to denote the first entry.
(*Reader) SeekPC <- go1.7
|
|
SeekPC returns the Entry for the compilation unit that includes pc, and positions the reader to read the children of that unit. If pc is not covered by any unit, SeekPC returns ErrUnknownPC and the position of the reader is undefined.
Because compilation units can describe multiple regions of the executable, in the worst case SeekPC must search through all the ranges in all the compilation units. Each call to SeekPC starts the search at the compilation unit of the last call, so in general looking up a series of PCs will be faster if they are sorted. If the caller wishes to do repeated fast PC lookups, it should build an appropriate index using the Ranges method.
(*Reader) SkipChildren
|
|
SkipChildren skips over the child entries associated with the last Entry returned by Next. If that Entry did not have children or Next has not been called, SkipChildren is a no-op.
type StructField
|
|
A StructField represents a field in a struct, union, or C++ class type.
Bit Fields
The BitSize, BitOffset, and DataBitOffset fields describe the bit size and offset of data members declared as bit fields in C/C++ struct/union/class types.
BitSize is the number of bits in the bit field.
DataBitOffset, if non-zero, is the number of bits from the start of the enclosing entity (e.g. containing struct/class/union) to the start of the bit field. This corresponds to the DW_AT_data_bit_offset DWARF attribute that was introduced in DWARF 4.
BitOffset, if non-zero, is the number of bits between the most significant bit of the storage unit holding the bit field to the most significant bit of the bit field. Here “storage unit” is the type name before the bit field (for a field “unsigned x:17”, the storage unit is “unsigned”). BitOffset values can vary depending on the endianness of the system. BitOffset corresponds to the DW_AT_bit_offset DWARF attribute that was deprecated in DWARF 4 and removed in DWARF 5.
At most one of DataBitOffset and BitOffset will be non-zero; DataBitOffset/BitOffset will only be non-zero if BitSize is non-zero. Whether a C compiler uses one or the other will depend on compiler vintage and command line options.
Here is an example of C/C++ bit field use, along with what to expect in terms of DWARF bit offset info. Consider this code:
struct S {
int q;
int j:5;
int k:6;
int m:5;
int n:8;
} s;
For the code above, one would expect to see the following for DW_AT_bit_offset values (using GCC 8):
Little | Big
Endian | Endian
|
"j": 27 | 0
"k": 21 | 5
"m": 16 | 11
"n": 8 | 16
Note that in the above the offsets are purely with respect to the containing storage unit for j/k/m/n – these values won’t vary based on the size of prior data members in the containing struct.
If the compiler emits DW_AT_data_bit_offset, the expected values would be:
"j": 32
"k": 37
"m": 43
"n": 48
Here the value 32 for “j” reflects the fact that the bit field is preceded by other data members (recall that DW_AT_data_bit_offset values are relative to the start of the containing struct). Hence DW_AT_data_bit_offset values can be quite large for structs with many fields.
DWARF also allow for the possibility of base types that have non-zero bit size and bit offset, so this information is also captured for base types, but it is worth noting that it is not possible to trigger this behavior using mainstream languages.
type StructType
|
|
A StructType represents a struct, union, or C++ class type.
(*StructType) Defn
|
|
(*StructType) String
|
|
type Tag
|
|
A Tag is the classification (the type) of an Entry.
|
|
(Tag) GoString
|
|
(Tag) String
|
|
type Type
|
|
A Type conventionally represents a pointer to any of the specific Type structures (CharType, StructType, etc.).
type TypedefType
|
|
A TypedefType represents a named type.
(*TypedefType) Size
|
|
(*TypedefType) String
|
|
type UcharType
|
|
A UcharType represents an unsigned character type.
type UintType
|
|
A UintType represents an unsigned integer type.
type UnspecifiedType <- go1.4
|
|
An UnspecifiedType represents an implicit, unknown, ambiguous or nonexistent type.
type UnsupportedType <- go1.13
|
|
An UnsupportedType is a placeholder returned in situations where we encounter a type that isn’t supported.
(*UnsupportedType) String <- go1.13
|
|
type VoidType
|
|
A VoidType represents the C void type.
(*VoidType) String
|
|
2.6.3 - elf
elf
https://pkg.go.dev/debug/elf@go1.20.1
Package elf implements access to ELF object files.
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, only basic validation is done when parsing object files. As such, care should be taken when parsing untrusted inputs, as parsing malformed files may consume significant resources, or cause panics.
常量
|
|
Indexes into the Header.Ident array.
|
|
Magic number for the elf trampoline, chosen wisely to be an immediate value.
|
|
Initial magic number for ELF files.
|
|
|
|
变量
|
|
ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols if there is no such section in the File.
函数
func R_INFO
|
|
func R_INFO32
|
|
func R_SYM32
|
|
func R_SYM64
|
|
func R_TYPE32
|
|
func R_TYPE64
|
|
func ST_INFO
|
|
类型
type Chdr32 <- go1.6
|
|
ELF32 Compression header.
type Chdr64 <- go1.6
|
|
ELF64 Compression header.
type Class
|
|
Class is found in Header.Ident[EI_CLASS] and Header.Class.
|
|
(Class) GoString
|
|
(Class) String
|
|
type CompressionType <- go1.6
|
|
Section compression type.
|
|
(CompressionType) GoString <- go1.6
|
|
(CompressionType) String <- go1.6
|
|
type Data
|
|
Data is found in Header.Ident[EI_DATA] and Header.Data.
|
|
(Data) GoString
|
|
(Data) String
|
|
type Dyn32
|
|
ELF32 Dynamic structure. The “.dynamic” section contains an array of them.
type Dyn64
|
|
ELF64 Dynamic structure. The “.dynamic” section contains an array of them.
type DynFlag
|
|
DT_FLAGS values.
|
|
(DynFlag) GoString
|
|
(DynFlag) String
|
|
type DynTag
|
|
Dyn.Tag
|
|
(DynTag) GoString
|
|
(DynTag) String
|
|
type File
|
|
A File represents an open ELF file.
func NewFile
|
|
NewFile creates a new File for accessing an ELF binary in an underlying reader. The ELF binary is expected to start at position 0 in the ReaderAt.
func Open
|
|
Open opens the named file using os.Open and prepares it for use as an ELF binary.
(*File) Close
|
|
Close closes the File. If the File was created using NewFile directly instead of Open, Close has no effect.
(*File) DWARF
|
|
(*File) DynString <- go1.1
|
|
DynString returns the strings listed for the given tag in the file’s dynamic section.
The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or DT_RUNPATH.
(*File) DynamicSymbols <- go1.4
|
|
DynamicSymbols returns the dynamic symbol table for f. The symbols will be listed in the order they appear in f.
If f has a symbol version table, the returned Symbols will have initialized Version and Library fields.
For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0. After retrieving the symbols as symtab, an externally supplied index x corresponds to symtab[x-1], not symtab[x].
(*File) ImportedLibraries
|
|
ImportedLibraries returns the names of all libraries referred to by the binary f that are expected to be linked with the binary at dynamic link time.
(*File) ImportedSymbols
|
|
ImportedSymbols returns the names of all symbols referred to by the binary f that are expected to be satisfied by other libraries at dynamic load time. It does not return weak symbols.
(*File) Section
|
|
Section returns a section with the given name, or nil if no such section exists.
(*File) SectionByType
|
|
SectionByType returns the first section in f with the given type, or nil if there is no such section.
(*File) Symbols
|
|
Symbols returns the symbol table for f. The symbols will be listed in the order they appear in f.
For compatibility with Go 1.0, Symbols omits the null symbol at index 0. After retrieving the symbols as symtab, an externally supplied index x corresponds to symtab[x-1], not symtab[x].
type FileHeader
|
|
A FileHeader represents an ELF file header.
type FormatError
|
|
(*FormatError) Error
|
|
type Header32
|
|
ELF32 File header.
type Header64
|
|
ELF64 file header.
type ImportedSymbol
|
|
type Machine
|
|
Machine is found in Header.Machine.
|
|
(Machine) GoString
|
|
(Machine) String
|
|
type NType
|
|
NType values; used in core files.
|
|
(NType) GoString
|
|
(NType) String
|
|
type OSABI
|
|
OSABI is found in Header.Ident[EI_OSABI] and Header.OSABI.
|
|
(OSABI) GoString
|
|
(OSABI) String
|
|
type Prog
|
|
A Prog represents a single ELF program header in an ELF binary.
(*Prog) Open
|
|
Open returns a new ReadSeeker reading the ELF program body.
type Prog32
|
|
ELF32 Program header.
type Prog64
|
|
ELF64 Program header.
type ProgFlag
|
|
Prog.Flag
|
|
(ProgFlag) GoString
|
|
(ProgFlag) String
|
|
type ProgHeader
|
|
A ProgHeader represents a single ELF program header.
type ProgType
|
|
Prog.Type
|
|
(ProgType) GoString
|
|
(ProgType) String
|
|
type R_386
|
|
Relocation types for 386.
|
|
(R_386) GoString
|
|
(R_386) String
|
|
type R_390 <- go1.7
|
|
Relocation types for s390x processors.
|
|
(R_390) GoString <- go1.7
|
|
(R_390) String <- go1.7
|
|
type R_AARCH64 <- go1.4
|
|
Relocation types for AArch64 (aka arm64)
|
|
(R_AARCH64) GoString <- go1.4
|
|
(R_AARCH64) String <- go1.4
|
|
type R_ALPHA
|
|
Relocation types for Alpha.
|
|
(R_ALPHA) GoString
|
|
(R_ALPHA) String
|
|
type R_ARM
|
|
Relocation types for ARM.
|
|
(R_ARM) GoString
|
|
(R_ARM) String
|
|
type R_LARCH <- go1.19
|
|
Relocation types for LoongArch.
|
|
(R_LARCH) GoString <- go1.19
|
|
(R_LARCH) String <- go1.19
|
|
type R_MIPS <- go1.6
|
|
Relocation types for MIPS.
|
|
(R_MIPS) GoString <- go1.6
|
|
(R_MIPS) String <- go1.6
|
|
type R_PPC
|
|
Relocation types for PowerPC.
Values that are shared by both R_PPC and R_PPC64 are prefixed with R_POWERPC_ in the ELF standard. For the R_PPC type, the relevant shared relocations have been renamed with the prefix R_PPC_. The original name follows the value in a comment.
|
|
(R_PPC) GoString
|
|
(R_PPC) String
|
|
type R_PPC64 <- go1.5
|
|
Relocation types for 64-bit PowerPC or Power Architecture processors.
Values that are shared by both R_PPC and R_PPC64 are prefixed with R_POWERPC_ in the ELF standard. For the R_PPC64 type, the relevant shared relocations have been renamed with the prefix R_PPC64_. The original name follows the value in a comment.
|
|
(R_PPC64) GoString <- go1.5
|
|
(R_PPC64) String <- go1.5
|
|
type R_RISCV <- go1.11
|
|
Relocation types for RISC-V processors.
|
|
(R_RISCV) GoString <- go1.11
|
|
(R_RISCV) String <- go1.11
|
|
type R_SPARC
|
|
Relocation types for SPARC.
|
|
(R_SPARC) GoString
|
|
(R_SPARC) String
|
|
type R_X86_64
|
|
Relocation types for x86-64.
|
|
(R_X86_64) GoString
|
|
(R_X86_64) String
|
|
type Rel32
|
|
ELF32 Relocations that don’t need an addend field.
type Rel64
|
|
ELF64 relocations that don’t need an addend field.
type Rela32
|
|
ELF32 Relocations that need an addend field.
type Rela64
|
|
ELF64 relocations that need an addend field.
type Section
|
|
A Section represents a single section in an ELF file.
(*Section) Data
|
|
Data reads and returns the contents of the ELF section. Even if the section is stored compressed in the ELF file, Data returns uncompressed data.
For an SHT_NOBITS section, Data always returns a non-nil error.
(*Section) Open
|
|
Open returns a new ReadSeeker reading the ELF section. Even if the section is stored compressed in the ELF file, the ReadSeeker reads uncompressed data.
For an SHT_NOBITS section, all calls to the opened reader will return a non-nil error.
type Section32
|
|
ELF32 Section header.
type Section64
|
|
ELF64 Section header.
type SectionFlag
|
|
Section flags.
|
|
(SectionFlag) GoString
|
|
(SectionFlag) String
|
|
type SectionHeader
|
|
A SectionHeader represents a single ELF section header.
type SectionIndex
|
|
Special section indices.
|
|
(SectionIndex) GoString
|
|
(SectionIndex) String
|
|
type SectionType
|
|
Section type.
|
|
(SectionType) GoString
|
|
(SectionType) String
|
|
type Sym32
|
|
ELF32 Symbol.
type Sym64
|
|
ELF64 symbol table entries.
type SymBind
|
|
Symbol Binding - ELFNN_ST_BIND - st_info
|
|
func ST_BIND
|
|
(SymBind) GoString
|
|
(SymBind) String
|
|
type SymType
|
|
Symbol type - ELFNN_ST_TYPE - st_info
|
|
func ST_TYPE
|
|
(SymType) GoString
|
|
(SymType) String
|
|
type SymVis
|
|
Symbol visibility - ELFNN_ST_VISIBILITY - st_other
|
|
func ST_VISIBILITY
|
|
(SymVis) GoString
|
|
(SymVis) String
|
|
type Symbol
|
|
A Symbol represents an entry in an ELF symbol table section.
type Type
|
|
Type is found in Header.Type.
|
|
(Type) GoString
|
|
(Type) String
|
|
type Version
|
|
Version is found in Header.Ident[EI_VERSION] and Header.Version.
|
|
(Version) GoString
|
|
(Version) String
|
|
2.6.4 - gosym
gosym
https://pkg.go.dev/debug/gosym@go1.20.1
Package gosym implements access to the Go symbol and line number tables embedded in Go binaries generated by the gc compilers.
常量
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type DecodingError
|
|
DecodingError represents an error during the decoding of the symbol table.
(*DecodingError) Error
|
|
type Func
|
|
A Func collects information about a single function.
type LineTable
|
|
A LineTable is a data structure mapping program counters to line numbers.
In Go 1.1 and earlier, each function (represented by a Func) had its own LineTable, and the line number corresponded to a numbering of all source lines in the program, across all files. That absolute line number would then have to be converted separately to a file name and line number within the file.
In Go 1.2, the format of the data changed so that there is a single LineTable for the entire program, shared by all Funcs, and there are no absolute line numbers, just line numbers within specific files.
For the most part, LineTable’s methods should be treated as an internal detail of the package; callers should use the methods on Table instead.
func NewLineTable
|
|
NewLineTable returns a new PC/line table corresponding to the encoded data. Text must be the start address of the corresponding text segment.
Example
|
|
Example
|
|
type Obj
|
|
An Obj represents a collection of functions in a symbol table.
The exact method of division of a binary into separate Objs is an internal detail of the symbol table format.
In early versions of Go each source file became a different Obj.
In Go 1 and Go 1.1, each package produced one Obj for all Go sources and one Obj per C source file.
In Go 1.2, there is a single Obj for the entire program.
type Sym
|
|
A Sym represents a single symbol table entry.
(*Sym) BaseName
|
|
BaseName returns the symbol name without the package or receiver name.
(*Sym) PackageName
|
|
PackageName returns the package part of the symbol name, or the empty string if there is none.
(*Sym) ReceiverName
|
|
ReceiverName returns the receiver type name of this symbol, or the empty string if there is none. A receiver name is only detected in the case that s.Name is fully-specified with a package name.
(*Sym) Static
|
|
Static reports whether this symbol is static (not visible outside its file).
type Table
|
|
Table represents a Go symbol table. It stores all of the symbols decoded from the program and provides methods to translate between symbols, names, and addresses.
func NewTable
|
|
NewTable decodes the Go symbol table (the “.gosymtab” section in ELF), returning an in-memory representation. Starting with Go 1.3, the Go symbol table no longer includes symbol data.
(*Table) LineToPC
|
|
LineToPC looks up the first program counter on the given line in the named file. It returns UnknownPathError or UnknownLineError if there is an error looking up this line.
(*Table) LookupFunc
|
|
LookupFunc returns the text, data, or bss symbol with the given name, or nil if no such symbol is found.
(*Table) LookupSym
|
|
LookupSym returns the text, data, or bss symbol with the given name, or nil if no such symbol is found.
(*Table) PCToFunc
|
|
PCToFunc returns the function containing the program counter pc, or nil if there is no such function.
(*Table) PCToLine
|
|
PCToLine looks up line number information for a program counter. If there is no information, it returns fn == nil.
(*Table) SymByAddr
|
|
SymByAddr returns the text, data, or bss symbol starting at the given address.
type UnknownFileError
|
|
UnknownFileError represents a failure to find the specific file in the symbol table.
(UnknownFileError) Error
|
|
type UnknownLineError
|
|
UnknownLineError represents a failure to map a line to a program counter, either because the line is beyond the bounds of the file or because there is no code on the given line.
(*UnknownLineError) Error
|
|
2.6.5 - macho
macho
https://pkg.go.dev/debug/macho@go1.20.1
Package macho implements access to Mach-O object files.
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, only basic validation is done when parsing object files. As such, care should be taken when parsing untrusted inputs, as parsing malformed files may consume significant resources, or cause panics.
常量
|
|
|
|
变量
|
|
ErrNotFat is returned from NewFatFile or OpenFat when the file is not a universal binary but may be a thin binary, based on its magic number.
函数
This section is empty.
类型
type Cpu
|
|
A Cpu is a Mach-O cpu type.
|
|
(Cpu) GoString
|
|
(Cpu) String
|
|
type Dylib
|
|
A Dylib represents a Mach-O load dynamic library command.
type DylibCmd
|
|
A DylibCmd is a Mach-O load dynamic library command.
type Dysymtab
|
|
A Dysymtab represents a Mach-O dynamic symbol table command.
type DysymtabCmd
|
|
A DysymtabCmd is a Mach-O dynamic symbol table command.
type FatArch <- go1.3
|
|
A FatArch is a Mach-O File inside a FatFile.
type FatArchHeader <- go1.3
|
|
A FatArchHeader represents a fat header for a specific image architecture.
type FatFile <- go1.3
|
|
A FatFile is a Mach-O universal binary that contains at least one architecture.
func NewFatFile <- go1.3
|
|
NewFatFile creates a new FatFile for accessing all the Mach-O images in a universal binary. The Mach-O binary is expected to start at position 0 in the ReaderAt.
func OpenFat <- go1.3
|
|
OpenFat opens the named file using os.Open and prepares it for use as a Mach-O universal binary.
(*FatFile) Close <- go1.3
|
|
type File
|
|
A File represents an open Mach-O file.
func NewFile
|
|
NewFile creates a new File for accessing a Mach-O binary in an underlying reader. The Mach-O binary is expected to start at position 0 in the ReaderAt.
func Open
|
|
Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
(*File) Close
|
|
Close closes the File. If the File was created using NewFile directly instead of Open, Close has no effect.
(*File) DWARF
|
|
DWARF returns the DWARF debug information for the Mach-O file.
(*File) ImportedLibraries
|
|
ImportedLibraries returns the paths of all libraries referred to by the binary f that are expected to be linked with the binary at dynamic link time.
(*File) ImportedSymbols
|
|
ImportedSymbols returns the names of all symbols referred to by the binary f that are expected to be satisfied by other libraries at dynamic load time.
(*File) Section
|
|
Section returns the first section with the given name, or nil if no such section exists.
(*File) Segment
|
|
Segment returns the first Segment with the given name, or nil if no such segment exists.
type FileHeader
|
|
A FileHeader represents a Mach-O file header.
type FormatError
|
|
FormatError is returned by some operations if the data does not have the correct format for an object file.
(*FormatError) Error
|
|
type Load
|
|
A Load represents any Mach-O load command.
type LoadBytes
|
|
A LoadBytes is the uninterpreted bytes of a Mach-O load command.
(LoadBytes) Raw
|
|
type LoadCmd
|
|
A LoadCmd is a Mach-O load command.
|
|
(LoadCmd) GoString
|
|
(LoadCmd) String
|
|
type Nlist32
|
|
An Nlist32 is a Mach-O 32-bit symbol table entry.
type Nlist64
|
|
An Nlist64 is a Mach-O 64-bit symbol table entry.
type Regs386
|
|
Regs386 is the Mach-O 386 register structure.
type RegsAMD64
|
|
RegsAMD64 is the Mach-O AMD64 register structure.
type Reloc <- go1.10
|
|
A Reloc represents a Mach-O relocation.
type RelocTypeARM <- go1.10
|
|
(RelocTypeARM) GoString <- go1.10
|
|
(RelocTypeARM) String <- go1.10
|
|
type RelocTypeARM64 <- go1.10
|
|
(RelocTypeARM64) GoString <- go1.10
|
|
(RelocTypeARM64) String <- go1.10
|
|
type RelocTypeGeneric <- go1.10
|
|
(RelocTypeGeneric) GoString <- go1.10
|
|
(RelocTypeGeneric) String <- go1.10
|
|
type RelocTypeX86_64 <- go1.10
|
|
(RelocTypeX86_64) GoString <- go1.10
|
|
(RelocTypeX86_64) String <- go1.10
|
|
type Rpath <- go1.10
|
|
A Rpath represents a Mach-O rpath command.
type RpathCmd <- go1.10
|
|
A RpathCmd is a Mach-O rpath command.
type Section
|
|
(*Section) Data
|
|
Data reads and returns the contents of the Mach-O section.
(*Section) Open
|
|
Open returns a new ReadSeeker reading the Mach-O section.
type Section32
|
|
A Section32 is a 32-bit Mach-O section header.
type Section64
|
|
A Section64 is a 64-bit Mach-O section header.
type SectionHeader
|
|
type Segment
|
|
A Segment represents a Mach-O 32-bit or 64-bit load segment command.
(*Segment) Data
|
|
Data reads and returns the contents of the segment.
(*Segment) Open
|
|
Open returns a new ReadSeeker reading the segment.
type Segment32
|
|
A Segment32 is a 32-bit Mach-O segment load command.
type Segment64
|
|
A Segment64 is a 64-bit Mach-O segment load command.
type SegmentHeader
|
|
A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command.
type Symbol
|
|
A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
type Symtab
|
|
A Symtab represents a Mach-O symbol table command.
type SymtabCmd
|
|
A SymtabCmd is a Mach-O symbol table command.
type Thread
|
|
A Thread is a Mach-O thread state command.
type Type
|
|
A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
|
|
(Type) GoString <- go1.10
|
|
(Type) String <- go1.10
|
|
2.6.6 - pe
pe
https://pkg.go.dev/debug/pe@go1.20.1
Package pe implements access to PE (Microsoft Windows Portable Executable) files.
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, only basic validation is done when parsing object files. As such, care should be taken when parsing untrusted inputs, as parsing malformed files may consume significant resources, or cause panics.
常量
|
|
|
|
IMAGE_DIRECTORY_ENTRY constants
|
|
Values of IMAGE_FILE_HEADER.Characteristics. These can be combined together.
|
|
OptionalHeader64.Subsystem and OptionalHeader32.Subsystem values.
|
|
OptionalHeader64.DllCharacteristics and OptionalHeader32.DllCharacteristics values. These can be combined together.
|
|
Section characteristics flags.
|
|
These constants make up the possible values for the ‘Selection’ field in an AuxFormat5.
|
|
变量
This section is empty.
函数
This section is empty.
类型
type COFFSymbol <- go1.1
|
|
COFFSymbol represents single COFF symbol table record.
(*COFFSymbol) FullName <- go1.8
|
|
FullName finds real name of symbol sym. Normally name is stored in sym.Name, but if it is longer then 8 characters, it is stored in COFF string table st instead.
type COFFSymbolAuxFormat5 <- go1.19
|
|
COFFSymbolAuxFormat5 describes the expected form of an aux symbol attached to a section definition symbol. The PE format defines a number of different aux symbol formats: format 1 for function definitions, format 2 for .be and .ef symbols, and so on. Format 5 holds extra info associated with a section definition, including number of relocations + line numbers, as well as COMDAT info. See https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-5-section-definitions for more on what’s going on here.
type DataDirectory <- go1.3
|
|
type File
|
|
A File represents an open PE file.
func NewFile
|
|
NewFile creates a new File for accessing a PE binary in an underlying reader.
func Open
|
|
Open opens the named file using os.Open and prepares it for use as a PE binary.
(*File) COFFSymbolReadSectionDefAux <- go1.19
|
|
COFFSymbolReadSectionDefAux returns a blob of axiliary information (including COMDAT info) for a section definition symbol. Here ‘idx’ is the index of a section symbol in the main COFFSymbol array for the File. Return value is a pointer to the appropriate aux symbol struct. For more info, see:
auxiliary symbols: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-symbol-records COMDAT sections: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#comdat-sections-object-only auxiliary info for section definitions: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-5-section-definitions
(*File) Close
|
|
Close closes the File. If the File was created using NewFile directly instead of Open, Close has no effect.
(*File) DWARF
|
|
(*File) ImportedLibraries
|
|
ImportedLibraries returns the names of all libraries referred to by the binary f that are expected to be linked with the binary at dynamic link time.
(*File) ImportedSymbols
|
|
ImportedSymbols returns the names of all symbols referred to by the binary f that are expected to be satisfied by other libraries at dynamic load time. It does not return weak symbols.
(*File) Section
|
|
Section returns the first section with the given name, or nil if no such section exists.
type FileHeader
|
|
type FormatError
|
|
FormatError is unused. The type is retained for compatibility.
(*FormatError) Error
|
|
type ImportDirectory
|
|
type OptionalHeader32 <- go1.3
|
|
type OptionalHeader64 <- go1.3
|
|
type Reloc <- go1.8
|
|
Reloc represents a PE COFF relocation. Each section contains its own relocation list.
type Section
|
|
Section provides access to PE COFF section.
(*Section) Data
|
|
Data reads and returns the contents of the PE section s.
(*Section) Open
|
|
Open returns a new ReadSeeker reading the PE section s.
type SectionHeader
|
|
SectionHeader is similar to SectionHeader32 with Name field replaced by Go string.
type SectionHeader32
|
|
SectionHeader32 represents real PE COFF section header.
type StringTable <- go1.8
|
|
StringTable is a COFF string table.
(StringTable) String <- go1.8
|
|
String extracts string from COFF string table st at offset start.
type Symbol <- go1.1
|
|
Symbol is similar to COFFSymbol with Name field replaced by Go string. Symbol also does not have NumberOfAuxSymbols.
2.6.7 - plan9obj
plan9obj
https://pkg.go.dev/debug/plan9obj@go1.20.1
Package plan9obj implements access to Plan 9 a.out object files.
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, only basic validation is done when parsing object files. As such, care should be taken when parsing untrusted inputs, as parsing malformed files may consume significant resources, or cause panics.
常量
|
|
变量
|
|
ErrNoSymbols is returned by File.Symbols if there is no such section in the File.
函数
This section is empty.
类型
type File
|
|
A File represents an open Plan 9 a.out file.
func NewFile
|
|
NewFile creates a new File for accessing a Plan 9 binary in an underlying reader. The Plan 9 binary is expected to start at position 0 in the ReaderAt.
func Open
|
|
Open opens the named file using os.Open and prepares it for use as a Plan 9 a.out binary.
(*File) Close
|
|
Close closes the File. If the File was created using NewFile directly instead of Open, Close has no effect.
(*File) Section
|
|
Section returns a section with the given name, or nil if no such section exists.
(*File) Symbols
|
|
Symbols returns the symbol table for f.
type FileHeader
|
|
A FileHeader represents a Plan 9 a.out file header.
type Section
|
|
A Section represents a single section in a Plan 9 a.out file.
(*Section) Data
|
|
Data reads and returns the contents of the Plan 9 a.out section.
(*Section) Open
|
|
Open returns a new ReadSeeker reading the Plan 9 a.out section.
type SectionHeader
|
|
A SectionHeader represents a single Plan 9 a.out section header. This structure doesn’t exist on-disk, but eases navigation through the object file.
type Sym
|
|
A Symbol represents an entry in a Plan 9 a.out symbol table section.
2.7 - encoding
2.7.1 - ascii85
ascii85
https://pkg.go.dev/encoding/ascii85@go1.20.1
Package ascii85 implements the ascii85 data encoding as used in the btoa tool and Adobe’s PostScript and PDF document formats.
常量
This section is empty.
变量
This section is empty.
函数
func Decode
|
|
Decode decodes src into dst, returning both the number of bytes written to dst and the number consumed from src. If src contains invalid ascii85 data, Decode will return the number of bytes successfully written and a CorruptInputError. Decode ignores space and control characters in src. Often, ascii85-encoded data is wrapped in <~ and ~> symbols. Decode expects these to have been stripped by the caller.
If flush is true, Decode assumes that src represents the end of the input stream and processes it completely rather than wait for the completion of another 32-bit block.
NewDecoder wraps an io.Reader interface around Decode.
func Encode
|
|
Encode encodes src into at most MaxEncodedLen(len(src)) bytes of dst, returning the actual number of bytes written.
The encoding handles 4-byte chunks, using a special encoding for the last fragment, so Encode is not appropriate for use on individual blocks of a large data stream. Use NewEncoder() instead.
Often, ascii85-encoded data is wrapped in <~ and ~> symbols. Encode does not add these.
func MaxEncodedLen
|
|
MaxEncodedLen returns the maximum length of an encoding of n source bytes.
func NewDecoder
|
|
NewDecoder constructs a new ascii85 stream decoder.
func NewEncoder
|
|
NewEncoder returns a new ascii85 stream encoder. Data written to the returned writer will be encoded and then written to w. Ascii85 encodings operate in 32-bit blocks; when finished writing, the caller must Close the returned encoder to flush any trailing partial block.
类型
type CorruptInputError
|
|
(CorruptInputError) Error
|
|
2.7.2 - asn1
asn1
https://pkg.go.dev/encoding/asn1@go1.20.1
Package asn1 implements parsing of DER-encoded ASN.1 data structures, as defined in ITU-T Rec X.690.
See also “A Layman’s Guide to a Subset of ASN.1, BER, and DER,” http://luca.ntop.org/Teaching/Appunti/asn1.html.
常量
|
|
ASN.1 tags represent the type of the following object.
|
|
ASN.1 class types represent the namespace of the tag.
变量
|
|
NullBytes contains bytes representing the DER-encoded ASN.1 NULL type.
|
|
NullRawValue is a RawValue with its Tag set to the ASN.1 NULL type tag (5).
函数
func Marshal
|
|
Marshal returns the ASN.1 encoding of val.
In addition to the struct tags recognised by Unmarshal, the following can be used:
ia5: causes strings to be marshaled as ASN.1, IA5String values
omitempty: causes empty slices to be skipped
printable: causes strings to be marshaled as ASN.1, PrintableString values
utf8: causes strings to be marshaled as ASN.1, UTF8String values
utc: causes time.Time to be marshaled as ASN.1, UTCTime values
generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
func MarshalWithParams <- go1.10
|
|
MarshalWithParams allows field parameters to be specified for the top-level element. The form of the params is the same as the field tags.
func Unmarshal
|
|
Unmarshal parses the DER-encoded ASN.1 data structure b and uses the reflect package to fill in an arbitrary value pointed at by val. Because Unmarshal uses the reflect package, the structs being written to must use upper case field names. If val is nil or not a pointer, Unmarshal returns an error.
After parsing b, any bytes that were leftover and not used to fill val will be returned in rest. When parsing a SEQUENCE into a struct, any trailing elements of the SEQUENCE that do not have matching fields in val will not be included in rest, as these are considered valid elements of the SEQUENCE and not trailing data.
An ASN.1 INTEGER can be written to an int, int32, int64, or *big.Int (from the math/big package). If the encoded value does not fit in the Go type, Unmarshal returns a parse error.
An ASN.1 BIT STRING can be written to a BitString.
An ASN.1 OCTET STRING can be written to a []byte.
An ASN.1 OBJECT IDENTIFIER can be written to an ObjectIdentifier.
An ASN.1 ENUMERATED can be written to an Enumerated.
An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a time.Time.
An ASN.1 PrintableString, IA5String, or NumericString can be written to a string.
Any of the above ASN.1 values can be written to an interface{}. The value stored in the interface has the corresponding Go type. For integers, that type is int64.
An ASN.1 SEQUENCE OF x or SET OF x can be written to a slice if an x can be written to the slice’s element type.
An ASN.1 SEQUENCE or SET can be written to a struct if each of the elements in the sequence can be written to the corresponding element in the struct.
The following tags on struct fields have special meaning to Unmarshal:
application specifies that an APPLICATION tag is used
private specifies that a PRIVATE tag is used
default:x sets the default value for optional integer fields (only used if optional is also present)
explicit specifies that an additional, explicit tag wraps the implicit one
optional marks the field as ASN.1 OPTIONAL
set causes a SET, rather than a SEQUENCE type to be expected
tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
When decoding an ASN.1 value with an IMPLICIT tag into a string field, Unmarshal will default to a PrintableString, which doesn’t support characters such as ‘@’ and ‘&’. To force other encodings, use the following tags:
ia5 causes strings to be unmarshaled as ASN.1 IA5String values
numeric causes strings to be unmarshaled as ASN.1 NumericString values
utf8 causes strings to be unmarshaled as ASN.1 UTF8String values
If the type of the first field of a structure is RawContent then the raw ASN1 contents of the struct will be stored in it.
If the name of a slice type ends with “SET” then it’s treated as if the “set” tag was set on it. This results in interpreting the type as a SET OF x rather than a SEQUENCE OF x. This can be used with nested slices where a struct tag cannot be given.
Other ASN.1 types are not supported; if it encounters them, Unmarshal returns a parse error.
func UnmarshalWithParams
|
|
UnmarshalWithParams allows field parameters to be specified for the top-level element. The form of the params is the same as the field tags.
类型
type BitString
|
|
BitString is the structure to use when you want an ASN.1 BIT STRING type. A bit string is padded up to the nearest byte in memory and the number of valid bits is recorded. Padding bits will be zero.
(BitString) At
|
|
At returns the bit at the given index. If the index is out of range it returns 0.
(BitString) RightAlign
|
|
RightAlign returns a slice where the padding bits are at the beginning. The slice may share memory with the BitString.
type Enumerated
|
|
An Enumerated is represented as a plain int.
type Flag
|
|
A Flag accepts any data and is set to true if present.
type ObjectIdentifier
|
|
An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
(ObjectIdentifier) Equal
|
|
Equal reports whether oi and other represent the same identifier.
(ObjectIdentifier) String <- go1.3
|
|
type RawContent
|
|
RawContent is used to signal that the undecoded, DER data needs to be preserved for a struct. To use it, the first field of the struct must have this type. It’s an error for any of the other fields to have this type.
type RawValue
|
|
A RawValue represents an undecoded ASN.1 object.
type StructuralError
|
|
A StructuralError suggests that the ASN.1 data is valid, but the Go type which is receiving it doesn’t match.
(StructuralError) Error
|
|
type SyntaxError
|
|
A SyntaxError suggests that the ASN.1 data is invalid.
(SyntaxError) Error
|
|
2.7.3 - base32
base32
https://pkg.go.dev/encoding/base32@go1.20.1
Package base32 implements base32 encoding as specified by RFC 4648.
常量
|
|
变量
|
|
HexEncoding is the “Extended Hex Alphabet” defined in RFC 4648. It is typically used in DNS.
|
|
StdEncoding is the standard base32 encoding, as defined in RFC 4648.
函数
func NewDecoder
|
|
NewDecoder constructs a new base32 stream decoder.
func NewEncoder
|
|
NewEncoder returns a new base32 stream encoder. Data written to the returned writer will be encoded using enc and then written to w. Base32 encodings operate in 5-byte blocks; when finished writing, the caller must Close the returned encoder to flush any partially written blocks.
Example
|
|
类型
type CorruptInputError
|
|
(CorruptInputError) Error
|
|
type Encoding
|
|
An Encoding is a radix 32 encoding/decoding scheme, defined by a 32-character alphabet. The most common is the “base32” encoding introduced for SASL GSSAPI and standardized in RFC 4648. The alternate “base32hex” encoding is used in DNSSEC.
func NewEncoding
|
|
NewEncoding returns a new Encoding defined by the given alphabet, which must be a 32-byte string.
(*Encoding) Decode
|
|
Decode decodes src using the encoding enc. It writes at most DecodedLen(len(src)) bytes to dst and returns the number of bytes written. If src contains invalid base32 data, it will return the number of bytes successfully written and CorruptInputError. New line characters (\r and \n) are ignored.
Example
|
|
(*Encoding) DecodeString
|
|
DecodeString returns the bytes represented by the base32 string s.
Example
|
|
(*Encoding) DecodedLen
|
|
DecodedLen returns the maximum length in bytes of the decoded data corresponding to n bytes of base32-encoded data.
(*Encoding) Encode
|
|
Encode encodes src using the encoding enc, writing EncodedLen(len(src)) bytes to dst.
The encoding pads the output to a multiple of 8 bytes, so Encode is not appropriate for use on individual blocks of a large data stream. Use NewEncoder() instead.
Example
|
|
(*Encoding) EncodeToString
|
|
EncodeToString returns the base32 encoding of src.
Example
|
|
(*Encoding) EncodedLen
|
|
EncodedLen returns the length in bytes of the base32 encoding of an input buffer of length n.
(Encoding) WithPadding <- go1.9
|
|
WithPadding creates a new encoding identical to enc except with a specified padding character, or NoPadding to disable padding. The padding character must not be ‘\r’ or ‘\n’, must not be contained in the encoding’s alphabet and must be a rune equal or below ‘\xff’.
2.7.4 - base64
base64
https://pkg.go.dev/encoding/base64@go1.20.1
Package base64 implements base64 encoding as specified by RFC 4648.
包 base64 实现了 RFC 4648 所规定的 base64 编码。
Example
|
|
常量
|
|
变量
|
|
RawStdEncoding is the standard raw, unpadded base64 encoding, as defined in RFC 4648 section 3.2. This is the same as StdEncoding but omits padding characters.
RawStdEncoding是标准的原始、无填充的base64编码,定义于RFC 4648第3.2节。这与StdEncoding相同,但省略了填充字符。
|
|
RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648. It is typically used in URLs and file names. This is the same as URLEncoding but omits padding characters.
RawURLEncoding是RFC 4648中定义的无填充的另一种base64编码。它通常在URL和文件名中使用。这与URLEncoding相同,但省略了填充字符。
|
|
StdEncoding is the standard base64 encoding, as defined in RFC 4648.
StdEncoding是标准的base64编码,如RFC 4648所定义。
|
|
URLEncoding is the alternate base64 encoding defined in RFC 4648. It is typically used in URLs and file names.
URLEncoding是RFC 4648中定义的备用base64编码。它通常在URL和文件名中使用。
函数
func NewDecoder
|
|
NewDecoder constructs a new base64 stream decoder.
NewDecoder构建一个新的base64流解码器。
func NewEncoder
|
|
NewEncoder returns a new base64 stream encoder. Data written to the returned writer will be encoded using enc and then written to w. Base64 encodings operate in 4-byte blocks; when finished writing, the caller must Close the returned encoder to flush any partially written blocks.
NewEncoder返回一个新的base64流编码器。写入返回的写入器的数据将使用enc进行编码,然后写入w。Base64编码以4字节的块进行操作;当写完后,调用者必须关闭返回的编码器以冲刷任何部分写入的块。
Example
|
|
类型
type CorruptInputError
|
|
(CorruptInputError) Error
|
|
type Encoding
|
|
An Encoding is a radix 64 encoding/decoding scheme, defined by a 64-character alphabet. The most common encoding is the “base64” encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM (RFC 1421). RFC 4648 also defines an alternate encoding, which is the standard encoding with - and _ substituted for + and /.
编码是一个弧度为64的编码/解码方案,由一个64字符的字母表定义。最常见的编码是RFC 4648中定义的 “base64 “编码,在MIME(RFC 2045)和PEM(RFC 1421)中使用。RFC 4648还定义了一个备用编码,即用-和_代替+和/的标准编码。
func NewEncoding
|
|
NewEncoding returns a new padded Encoding defined by the given alphabet, which must be a 64-byte string that does not contain the padding character or CR / LF (’\r’, ‘\n’). The resulting Encoding uses the default padding character (’=’), which may be changed or disabled via WithPadding.
NewEncoding返回一个由给定字母定义的新的填充编码,它必须是一个64字节的字符串,不包含填充字符或CR / LF(’\r’, ‘\n’)。产生的Encoding使用默认的padding字符(’=’),可以通过WithPadding改变或禁用。
(*Encoding) Decode
|
|
Decode decodes src using the encoding enc. It writes at most DecodedLen(len(src)) bytes to dst and returns the number of bytes written. If src contains invalid base64 data, it will return the number of bytes successfully written and CorruptInputError. New line characters (\r and \n) are ignored.
Decode使用enc编码对src进行解码。它最多向dst写入DecodedLen(len(src))字节,并返回写入的字节数。如果src包含无效的base64数据,它将返回成功写入的字节数和CorruptInputError。新行字符(\r 和 \n)被忽略。
Example
|
|
(*Encoding) DecodeString
|
|
DecodeString returns the bytes represented by the base64 string s.
DecodeString返回base64字符串s所代表的字节。
Example
|
|
(*Encoding) DecodedLen
|
|
DecodedLen returns the maximum length in bytes of the decoded data corresponding to n bytes of base64-encoded data.
DecodedLen返回对应于base64编码的n个字节的解码数据的最大长度(字节)。
(*Encoding) Encode
|
|
Encode encodes src using the encoding enc, writing EncodedLen(len(src)) bytes to dst.
Encode使用enc编码对src进行编码,向dst写入EncodedLen(len(src))字节。
The encoding pads the output to a multiple of 4 bytes, so Encode is not appropriate for use on individual blocks of a large data stream. Use NewEncoder() instead.
编码将输出填充为4字节的倍数,所以Encode不适合用于大数据流的单个块。请使用NewEncoder()代替。
Example
|
|
(*Encoding) EncodeToString
|
|
EncodeToString returns the base64 encoding of src.
EncodeToString返回src的base64编码。
Example
|
|
(*Encoding) EncodedLen
|
|
EncodedLen returns the length in bytes of the base64 encoding of an input buffer of length n.
EncodedLen返回一个长度为n的输入缓冲区的base64编码的字节长度。
(Encoding) Strict <- go1.8
|
|
Strict creates a new encoding identical to enc except with strict decoding enabled. In this mode, the decoder requires that trailing padding bits are zero, as described in RFC 4648 section 3.5.
严格创建一个与enc相同的新编码,只是启用了严格解码。在这种模式下,解码器要求尾部填充位为零,如RFC 4648第3.5节所述。
Note that the input is still malleable, as new line characters (CR and LF) are still ignored.
注意,输入仍然是可塑的,因为新的行字符(CR和LF)仍然被忽略。
(Encoding) WithPadding <- go1.5
|
|
WithPadding creates a new encoding identical to enc except with a specified padding character, or NoPadding to disable padding. The padding character must not be ‘\r’ or ‘\n’, must not be contained in the encoding’s alphabet and must be a rune equal or below ‘\xff’.
WithPadding创建一个与enc相同的新编码,除了指定的padding字符,或者用NoPadding来禁用padding。填充字符不能是’\r’或’\n’,不能包含在编码的字母表中,必须是等于或低于’\xff’的符文。
2.7.5 - binary
binary
https://pkg.go.dev/encoding/binary@go1.20.1
Package binary implements simple translation between numbers and byte sequences and encoding and decoding of varints.
Numbers are translated by reading and writing fixed-size values. A fixed-size value is either a fixed-size arithmetic type (bool, int8, uint8, int16, float32, complex64, …) or an array or struct containing only fixed-size values.
The varint functions encode and decode single integer values using a variable-length encoding; smaller values require fewer bytes. For a specification, see https://developers.google.com/protocol-buffers/docs/encoding.
This package favors simplicity over efficiency. Clients that require high-performance serialization, especially for large data structures, should look at more advanced solutions such as the encoding/gob package or protocol buffers.
常量
|
|
MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
变量
|
|
BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder.
|
|
LittleEndian is the little-endian implementation of ByteOrder and AppendByteOrder.
函数
func AppendUvarint <- go1.19
|
|
AppendUvarint appends the varint-encoded form of x, as generated by PutUvarint, to buf and returns the extended buffer.
func AppendVarint <- go1.19
|
|
AppendVarint appends the varint-encoded form of x, as generated by PutVarint, to buf and returns the extended buffer.
func PutUvarint
|
|
PutUvarint encodes a uint64 into buf and returns the number of bytes written. If the buffer is too small, PutUvarint will panic.
Example
|
|
func PutVarint
|
|
PutVarint encodes an int64 into buf and returns the number of bytes written. If the buffer is too small, PutVarint will panic.
Example
|
|
func Read
|
|
Read reads structured binary data from r into data. Data must be a pointer to a fixed-size value or a slice of fixed-size values. Bytes read from r are decoded using the specified byte order and written to successive fields of the data. When decoding boolean values, a zero byte is decoded as false, and any other non-zero byte is decoded as true. When reading into structs, the field data for fields with blank (_) field names is skipped; i.e., blank field names may be used for padding. When reading into a struct, all non-blank fields must be exported or Read may panic.
The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, Read returns ErrUnexpectedEOF.
Example
|
|
Example
|
|
func ReadUvarint
|
|
ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadUvarint returns io.ErrUnexpectedEOF.
func ReadVarint
|
|
ReadVarint reads an encoded signed integer from r and returns it as an int64. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadVarint returns io.ErrUnexpectedEOF.
func Size
|
|
Size returns how many bytes Write would generate to encode the value v, which must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. If v is neither of these, Size returns -1.
func Uvarint
|
|
Uvarint decodes a uint64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 meaning:
n == 0: buf too small
n < 0: value larger than 64 bits (overflow)
and -n is the number of bytes read
Example
|
|
func Varint
|
|
Varint decodes an int64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 with the following meaning:
n == 0: buf too small
n < 0: value larger than 64 bits (overflow)
and -n is the number of bytes read
Example
|
|
func Write
|
|
Write writes the binary representation of data into w. Data must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. Boolean values encode as one byte: 1 for true, and 0 for false. Bytes written to w are encoded using the specified byte order and read from successive fields of the data. When writing structs, zero values are written for fields with blank (_) field names.
Example
|
|
Example
|
|
类型
type AppendByteOrder <- go1.19
|
|
AppendByteOrder specifies how to append 16-, 32-, or 64-bit unsigned integers into a byte slice.
type ByteOrder
|
|
A ByteOrder specifies how to convert byte slices into 16-, 32-, or 64-bit unsigned integers.
Example
|
|
2.7.6 - csv
csv
https://pkg.go.dev/encoding/csv@go1.20.1
Package csv reads and writes comma-separated values (CSV) files. There are many kinds of CSV files; this package supports the format described in RFC 4180.
csv包读取和写入逗号分隔的值(CSV)文件。有许多种CSV文件;这个包支持RFC 4180中描述的格式。
A csv file contains zero or more records of one or more fields per record. Each record is separated by the newline character. The final record may optionally be followed by a newline character.
一个csv文件包含零个或多个记录,每个记录有一个或多个字段。每条记录由换行符分隔。最后一条记录后面可以选择换行符。
field1,field2,field3
White space is considered part of a field.
白色空间被认为是字段的一部分。
Carriage returns before newline characters are silently removed.
换行符之前的回车符会被默默地删除。
Blank lines are ignored. A line with only whitespace characters (excluding the ending newline character) is not considered a blank line.
空白行被忽略。只有空白字符的行(不包括结尾的换行字符)不被视为空行。
Fields which start and stop with the quote character " are called quoted-fields. The beginning and ending quote are not part of the field.
以引号字符"“开始和结束的字段被称为引号字段。开始和结束的引号不是字段的一部分。
The source:
来源:
normal string,"quoted-field"
results in the fields
的结果是字段
{`normal string`, `quoted-field`}
Within a quoted-field a quote character followed by a second quote character is considered a single quote.
在一个带引号的字段内,一个引号字符后面的第二个引号字符被认为是一个单引号。
"the ""word"" is true","a ""quoted-field"""
results in
结果是
{`the "word" is true`, `a "quoted-field"`}
Newlines and commas may be included in a quoted-field
换行符和逗号可以包含在一个引号字段中。
"Multi-line
field","comma is ,"
results in
结果是
{`Multi-line
field`, `comma is ,`}
常量
This section is empty.
变量
|
|
These are the errors that can be returned in ParseError.Err.
这些是可以在ParseError.Err中返回的错误。
函数
This section is empty.
类型
type ParseError
|
|
A ParseError is returned for parsing errors. Line numbers are 1-indexed and columns are 0-indexed.
对于解析错误会返回一个ParseError。行号是1-索引的,列是0-索引的。
(*ParseError) Error
|
|
(*ParseError) Unwrap <- go1.13
|
|
type Reader
|
|
A Reader reads records from a CSV-encoded file.
Reader 从一个CSV编码的文件中读取记录。
As returned by NewReader, a Reader expects input conforming to RFC 4180. The exported fields can be changed to customize the details before the first call to Read or ReadAll.
正如NewReader所返回的那样,Reader期望输入的内容符合RFC 4180的规定。在第一次调用Read或ReadAll之前,导出的字段可以被改变以定制细节。
The Reader converts all \r\n sequences in its input to plain \n, including in multiline field values, so that the returned data does not depend on which line-ending convention an input file uses.
Reader 将其输入中的所有\r\n序列转换为普通的\n,包括在多行字段值中,因此返回的数据不依赖于输入文件使用的行结束惯例。
Example
|
|
Example
|
|
func NewReader
|
|
NewReader returns a new Reader that reads from r.
NewReader返回一个新的阅读器,从r中读取数据。
(*Reader) FieldPos <- go1.17
|
|
FieldPos returns the line and column corresponding to the start of the field with the given index in the slice most recently returned by Read. Numbering of lines and columns starts at 1; columns are counted in bytes, not runes.
FieldPos返回对应于最近由Read返回的片断中具有给定索引的字段开始的行和列。行和列的编号从1开始;列的计数单位是字节,而不是符码。
If this is called with an out-of-bounds index, it panics.
如果在调用这个函数时,索引超出了范围,它就会惊慌失措。
(*Reader) InputOffset <- go1.19
|
|
InputOffset returns the input stream byte offset of the current reader position. The offset gives the location of the end of the most recently read row and the beginning of the next row.
InputOffset返回当前阅读器位置的输入流字节偏移。这个偏移量给出了最近读取的行的结束和下一行的开始的位置。
(*Reader) Read
|
|
Read reads one record (a slice of fields) from r. If the record has an unexpected number of fields, Read returns the record along with the error ErrFieldCount. Except for that case, Read always returns either a non-nil record or a non-nil error, but not both. If there is no data left to be read, Read returns nil, io.EOF. If ReuseRecord is true, the returned slice may be shared between multiple calls to Read.
如果记录有一个意外的字段数,Read会返回记录和错误ErrFieldCount。除了这种情况,Read总是返回一个非空的记录或一个非空的错误,但不会同时返回。如果没有数据可读,Read返回nil,即io.EOF。如果ReuseRecord为真,返回的片断可以在多次调用Read时共享。
(*Reader) ReadAll
|
|
ReadAll reads all the remaining records from r. Each record is a slice of fields. A successful call returns err == nil, not err == io.EOF. Because ReadAll is defined to read until EOF, it does not treat end of file as an error to be reported.
ReadAll从r读取所有剩余的记录。一个成功的调用返回err == nil,而不是err == io.EOF。因为ReadAll被定义为读到EOF为止,它不把文件结束作为一个错误来报告。
Example
|
|
type Writer
|
|
A Writer writes records using CSV encoding.
Writer使用CSV编码来写记录。
As returned by NewWriter, a Writer writes records terminated by a newline and uses ‘,’ as the field delimiter. The exported fields can be changed to customize the details before the first call to Write or WriteAll.
正如NewWriter所返回的那样,Writer写入的记录以换行方式结束,并使用’,‘作为字段分隔符。在第一次调用Write或WriteAll之前,可以改变导出的字段以定制细节。
Comma is the field delimiter.
逗号是字段分隔符。
If UseCRLF is true, the Writer ends each output line with \r\n instead of \n.
如果UseCRLF为真,Writer会以\r\n而不是\n结束每个输出行。
The writes of individual records are buffered. After all data has been written, the client should call the Flush method to guarantee all data has been forwarded to the underlying io.Writer. Any errors that occurred should be checked by calling the Error method.
单个记录的写入是缓冲的。在所有数据被写入后,客户端应该调用Flush方法以保证所有数据都被转发到底层的io.Writer。任何发生的错误都应该通过调用Error方法来检查。
Example
|
|
func NewWriter
|
|
NewWriter returns a new Writer that writes to w.
NewWriter返回一个新的写入w的Writer。
(*Writer) Error <- go1.1
|
|
Error reports any error that has occurred during a previous Write or Flush.
Error报告在之前的写或刷新过程中发生的任何错误。
(*Writer) Flush
|
|
Flush writes any buffered data to the underlying io.Writer. To check if an error occurred during the Flush, call Error.
Flush将任何缓冲的数据写入底层的io.Writer。要检查在Flush过程中是否有错误发生,请调用Error。
(*Writer) Write
|
|
Write writes a single CSV record to w along with any necessary quoting. A record is a slice of strings with each string being one field. Writes are buffered, so Flush must eventually be called to ensure that the record is written to the underlying io.Writer.
Write将一条CSV记录和任何必要的引号一起写到w中。一个记录是一个字符串的切片,每个字符串是一个字段。写入是缓冲的,所以最终必须调用Flush以确保记录被写入底层的io.Writer。
(*Writer) WriteAll
|
|
WriteAll writes multiple CSV records to w using Write and then calls Flush, returning any error from the Flush.
WriteAll使用Write将多个CSV记录写入w,然后调用Flush,返回Flush的任何错误。
|
|
2.7.7 - encoding
encoding
https://pkg.go.dev/encoding@go1.20.1
Package encoding defines interfaces shared by other packages that convert data to and from byte-level and textual representations. Packages that check for these interfaces include encoding/gob, encoding/json, and encoding/xml. As a result, implementing an interface once can make a type useful in multiple encodings. Standard types that implement these interfaces include time.Time and net.IP. The interfaces come in pairs that produce and consume encoded data.
常量
This section is empty.
变量
This section is empty.
函数
This section is empty.
类型
type BinaryMarshaler
|
|
BinaryMarshaler is the interface implemented by an object that can marshal itself into a binary form.
MarshalBinary encodes the receiver into a binary form and returns the result.
type BinaryUnmarshaler
|
|
BinaryUnmarshaler is the interface implemented by an object that can unmarshal a binary representation of itself.
UnmarshalBinary must be able to decode the form generated by MarshalBinary. UnmarshalBinary must copy the data if it wishes to retain the data after returning.
type TextMarshaler
|
|
TextMarshaler is the interface implemented by an object that can marshal itself into a textual form.
MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
type TextUnmarshaler
|
|
TextUnmarshaler is the interface implemented by an object that can unmarshal a textual representation of itself.
UnmarshalText must be able to decode the form generated by MarshalText. UnmarshalText must copy the text if it wishes to retain the text after returning.
2.7.8 - gob
gob
https://pkg.go.dev/encoding/gob@go1.20.1
Package gob manages streams of gobs - binary values exchanged between an Encoder (transmitter) and a Decoder (receiver). A typical use is transporting arguments and results of remote procedure calls (RPCs) such as those provided by package “net/rpc”.
The implementation compiles a custom codec for each data type in the stream and is most efficient when a single Encoder is used to transmit a stream of values, amortizing the cost of compilation.
Basics
A stream of gobs is self-describing. Each data item in the stream is preceded by a specification of its type, expressed in terms of a small set of predefined types. Pointers are not transmitted, but the things they point to are transmitted; that is, the values are flattened. Nil pointers are not permitted, as they have no value. Recursive types work fine, but recursive values (data with cycles) are problematic. This may change.
To use gobs, create an Encoder and present it with a series of data items as values or addresses that can be dereferenced to values. The Encoder makes sure all type information is sent before it is needed. At the receive side, a Decoder retrieves values from the encoded stream and unpacks them into local variables.
类型
The source and destination values/types need not correspond exactly. For structs, fields (identified by name) that are in the source but absent from the receiving variable will be ignored. Fields that are in the receiving variable but missing from the transmitted type or value will be ignored in the destination. If a field with the same name is present in both, their types must be compatible. Both the receiver and transmitter will do all necessary indirection and dereferencing to convert between gobs and actual Go values. For instance, a gob type that is schematically,
struct { A, B int }
can be sent from or received into any of these Go types:
struct { A, B int } // the same
*struct { A, B int } // extra indirection of the struct
struct { *A, **B int } // extra indirection of the fields
struct { A, B int64 } // different concrete value type; see below
It may also be received into any of these:
struct { A, B int } // the same
struct { B, A int } // ordering doesn't matter; matching is by name
struct { A, B, C int } // extra field (C) ignored
struct { B int } // missing field (A) ignored; data will be dropped
struct { B, C int } // missing field (A) ignored; extra field (C) ignored.
Attempting to receive into these types will draw a decode error:
struct { A int; B uint } // change of signedness for B
struct { A int; B float } // change of type for B
struct { } // no field names in common
struct { C, D int } // no field names in common
Integers are transmitted two ways: arbitrary precision signed integers or arbitrary precision unsigned integers. There is no int8, int16 etc. discrimination in the gob format; there are only signed and unsigned integers. As described below, the transmitter sends the value in a variable-length encoding; the receiver accepts the value and stores it in the destination variable. Floating-point numbers are always sent using IEEE-754 64-bit precision (see below).
Signed integers may be received into any signed integer variable: int, int16, etc.; unsigned integers may be received into any unsigned integer variable; and floating point values may be received into any floating point variable. However, the destination variable must be able to represent the value or the decode operation will fail.
Structs, arrays and slices are also supported. Structs encode and decode only exported fields. Strings and arrays of bytes are supported with a special, efficient representation (see below). When a slice is decoded, if the existing slice has capacity the slice will be extended in place; if not, a new array is allocated. Regardless, the length of the resulting slice reports the number of elements decoded.
In general, if allocation is required, the decoder will allocate memory. If not, it will update the destination variables with values read from the stream. It does not initialize them first, so if the destination is a compound value such as a map, struct, or slice, the decoded values will be merged elementwise into the existing variables.
Functions and channels will not be sent in a gob. Attempting to encode such a value at the top level will fail. A struct field of chan or func type is treated exactly like an unexported field and is ignored.
Gob can encode a value of any type implementing the GobEncoder or encoding.BinaryMarshaler interfaces by calling the corresponding method, in that order of preference.
Gob can decode a value of any type implementing the GobDecoder or encoding.BinaryUnmarshaler interfaces by calling the corresponding method, again in that order of preference.
Encoding Details
This section documents the encoding, details that are not important for most users. Details are presented bottom-up.
An unsigned integer is sent one of two ways. If it is less than 128, it is sent as a byte with that value. Otherwise it is sent as a minimal-length big-endian (high byte first) byte stream holding the value, preceded by one byte holding the byte count, negated. Thus 0 is transmitted as (00), 7 is transmitted as (07) and 256 is transmitted as (FE 01 00).
A boolean is encoded within an unsigned integer: 0 for false, 1 for true.
A signed integer, i, is encoded within an unsigned integer, u. Within u, bits 1 upward contain the value; bit 0 says whether they should be complemented upon receipt. The encode algorithm looks like this:
|
|
The low bit is therefore analogous to a sign bit, but making it the complement bit instead guarantees that the largest negative integer is not a special case. For example, -129=^128=(^256»1) encodes as (FE 01 01).
Floating-point numbers are always sent as a representation of a float64 value. That value is converted to a uint64 using math.Float64bits. The uint64 is then byte-reversed and sent as a regular unsigned integer. The byte-reversal means the exponent and high-precision part of the mantissa go first. Since the low bits are often zero, this can save encoding bytes. For instance, 17.0 is encoded in only three bytes (FE 31 40).
Strings and slices of bytes are sent as an unsigned count followed by that many uninterpreted bytes of the value.
All other slices and arrays are sent as an unsigned count followed by that many elements using the standard gob encoding for their type, recursively.
Maps are sent as an unsigned count followed by that many key, element pairs. Empty but non-nil maps are sent, so if the receiver has not allocated one already, one will always be allocated on receipt unless the transmitted map is nil and not at the top level.
In slices and arrays, as well as maps, all elements, even zero-valued elements, are transmitted, even if all the elements are zero.
Structs are sent as a sequence of (field number, field value) pairs. The field value is sent using the standard gob encoding for its type, recursively. If a field has the zero value for its type (except for arrays; see above), it is omitted from the transmission. The field number is defined by the type of the encoded struct: the first field of the encoded type is field 0, the second is field 1, etc. When encoding a value, the field numbers are delta encoded for efficiency and the fields are always sent in order of increasing field number; the deltas are therefore unsigned. The initialization for the delta encoding sets the field number to -1, so an unsigned integer field 0 with value 7 is transmitted as unsigned delta = 1, unsigned value = 7 or (01 07). Finally, after all the fields have been sent a terminating mark denotes the end of the struct. That mark is a delta=0 value, which has representation (00).
Interface types are not checked for compatibility; all interface types are treated, for transmission, as members of a single “interface” type, analogous to int or []byte - in effect they’re all treated as interface{}. Interface values are transmitted as a string identifying the concrete type being sent (a name that must be pre-defined by calling Register), followed by a byte count of the length of the following data (so the value can be skipped if it cannot be stored), followed by the usual encoding of concrete (dynamic) value stored in the interface value. (A nil interface value is identified by the empty string and transmits no value.) Upon receipt, the decoder verifies that the unpacked concrete item satisfies the interface of the receiving variable.
If a value is passed to Encode and the type is not a struct (or pointer to struct, etc.), for simplicity of processing it is represented as a struct of one field. The only visible effect of this is to encode a zero byte after the value, just as after the last field of an encoded struct, so that the decode algorithm knows when the top-level value is complete.
The representation of types is described below. When a type is defined on a given connection between an Encoder and Decoder, it is assigned a signed integer type id. When Encoder.Encode(v) is called, it makes sure there is an id assigned for the type of v and all its elements and then it sends the pair (typeid, encoded-v) where typeid is the type id of the encoded type of v and encoded-v is the gob encoding of the value v.
To define a type, the encoder chooses an unused, positive type id and sends the pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireType description, constructed from these types:
|
|
If there are nested type ids, the types for all inner type ids must be defined before the top-level type id is used to describe an encoded-v.
For simplicity in setup, the connection is defined to understand these types a priori, as well as the basic gob types int, uint, etc. Their ids are:
bool 1
int 2
uint 3
float 4
[]byte 5
string 6
complex 7
interface 8
// gap for reserved ids.
WireType 16
ArrayType 17
CommonType 18
SliceType 19
StructType 20
FieldType 21
// 22 is slice of fieldType.
MapType 23
Finally, each message created by a call to Encode is preceded by an encoded unsigned integer count of the number of bytes remaining in the message. After the initial type name, interface values are wrapped the same way; in effect, the interface value acts like a recursive invocation of Encode.
In summary, a gob stream looks like
(byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))*
where * signifies zero or more repetitions and the type id of a value must be predefined or be defined before the value in the stream.
Compatibility: Any future changes to the package will endeavor to maintain compatibility with streams encoded using previous versions. That is, any released version of this package should be able to decode data written with any previously released version, subject to issues such as security fixes. See the Go compatibility document for background: https://golang.org/doc/go1compat
See “Gobs of data” for a design discussion of the gob wire format: https://blog.golang.org/gobs-of-data
Security
This package is not designed to be hardened against adversarial inputs, and is outside the scope of https://go.dev/security/policy. In particular, the Decoder does only basic sanity checking on decoded input sizes, and its limits are not configurable. Care should be taken when decoding gob data from untrusted sources, which may consume significant resources.
Example
|
|
Example
|
|
Example
|
|
常量
This section is empty.
变量
This section is empty.
函数
func Register
|
|
Register records a type, identified by a value for that type, under its internal type name. That name will identify the concrete type of a value sent or received as an interface variable. Only types that will be transferred as implementations of interface values need to be registered. Expecting to be used only during initialization, it panics if the mapping between types and names is not a bijection.
func RegisterName
|
|
RegisterName is like Register but uses the provided name rather than the type’s default.
类型
type CommonType
|
|
CommonType holds elements of all types. It is a historical artifact, kept for binary compatibility and exported only for the benefit of the package’s encoding of type descriptors. It is not intended for direct use by clients.
type Decoder
|
|
A Decoder manages the receipt of type and data information read from the remote side of a connection. It is safe for concurrent use by multiple goroutines.
The Decoder does only basic sanity checking on decoded input sizes, and its limits are not configurable. Take caution when decoding gob data from untrusted sources.
func NewDecoder
|
|
NewDecoder returns a new decoder that reads from the io.Reader. If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
(*Decoder) Decode
|
|
Decode reads the next value from the input stream and stores it in the data represented by the empty interface value. If e is nil, the value will be discarded. Otherwise, the value underlying e must be a pointer to the correct type for the next data item received. If the input is at EOF, Decode returns io.EOF and does not modify e.
(*Decoder) DecodeValue
|
|
DecodeValue reads the next value from the input stream. If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value. Otherwise, it stores the value into v. In that case, v must represent a non-nil pointer to data or be an assignable reflect.Value (v.CanSet()) If the input is at EOF, DecodeValue returns io.EOF and does not modify v.
type Encoder
|
|
An Encoder manages the transmission of type and data information to the other side of a connection. It is safe for concurrent use by multiple goroutines.
func NewEncoder
|
|
NewEncoder returns a new encoder that will transmit on the io.Writer.
(*Encoder) Encode
|
|
Encode transmits the data item represented by the empty interface value, guaranteeing that all necessary type information has been transmitted first. Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob.
(*Encoder) EncodeValue
|
|
EncodeValue transmits the data item represented by the reflection value, guaranteeing that all necessary type information has been transmitted first. Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
type GobDecoder
|
|
GobDecoder is the interface describing data that provides its own routine for decoding transmitted values sent by a GobEncoder.
type GobEncoder
|
|
GobEncoder is the interface describing data that provides its own representation for encoding values for transmission to a GobDecoder. A type that implements GobEncoder and GobDecoder has complete control over the representation of its data and may therefore contain things such as private fields, channels, and functions, which are not usually transmissible in gob streams.
Note: Since gobs can be stored permanently, it is good design to guarantee the encoding used by a GobEncoder is stable as the software evolves. For instance, it might make sense for GobEncode to include a version number in the encoding.
2.7.9 - hex
hex
https://pkg.go.dev/encoding/hex@go1.20.1
Package hex implements hexadecimal encoding and decoding.
包hex实现了十六进制的编码和解码。
常量
This section is empty.
变量
|
|
ErrLength reports an attempt to decode an odd-length input using Decode or DecodeString. The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
ErrLength报告使用Decode或DecodeString解码一个奇长的输入的尝试。基于流的解码器返回io.ErrUnexpectedEOF而不是ErrLength。
函数
func Decode
|
|
Decode decodes src into DecodedLen(len(src)) bytes, returning the actual number of bytes written to dst.
Decode将src解码为DecodedLen(len(src))字节,返回写给dst的实际字节数。
Decode expects that src contains only hexadecimal characters and that src has even length. If the input is malformed, Decode returns the number of bytes decoded before the error.
解码期望src只包含十六进制的字符,并且src的长度是偶数。如果输入是畸形的,Decode会返回错误发生前的解码字节数。
Example
|
|
func DecodeString
|
|
DecodeString returns the bytes represented by the hexadecimal string s.
DecodeString返回十六进制字符串s所代表的字节数。
DecodeString expects that src contains only hexadecimal characters and that src has even length. If the input is malformed, DecodeString returns the bytes decoded before the error.
DecodeString期望src只包含十六进制的字符,并且src具有偶数长度。如果输入是畸形的,DecodeString将返回错误之前的解码字节。
Example
|
|
func DecodedLen
|
|
DecodedLen returns the length of a decoding of x source bytes. Specifically, it returns x / 2.
DecodedLen返回x个源字节的解码长度。具体来说,它返回x/2。
func Dump
|
|
Dump returns a string that contains a hex dump of the given data. The format of the hex dump matches the output of hexdump -C on the command line.
Dump返回一个包含给定数据的十六进制转储的字符串。十六进制转储的格式与命令行中hexdump -C的输出相匹配。
Example
|
|
func Dumper
|
|
Dumper returns a WriteCloser that writes a hex dump of all written data to w. The format of the dump matches the output of hexdump -C on the command line.
Dumper返回一个WriteCloser,将所有写入的数据的十六进制转储到w。
Example
|
|
func Encode
|
|
Encode encodes src into EncodedLen(len(src)) bytes of dst. As a convenience, it returns the number of bytes written to dst, but this value is always EncodedLen(len(src)). Encode implements hexadecimal encoding.
Encode将src编码为dst的EncodedLen(len(src))字节。为了方便起见,它返回写入dst的字节数,但这个值总是EncodedLen(len(src))。Encode实现了十六进制的编码。
Example
|
|
func EncodeToString
|
|
EncodeToString returns the hexadecimal encoding of src.
EncodeToString返回src的十六进制编码。
Example
|
|
func EncodedLen
|
|
EncodedLen returns the length of an encoding of n source bytes. Specifically, it returns n * 2.
EncodedLen返回n个源字节的编码的长度。具体来说,它返回n * 2。
func NewDecoder <- go1.10
|
|
NewDecoder returns an io.Reader that decodes hexadecimal characters from r. NewDecoder expects that r contain only an even number of hexadecimal characters.
NewDecoder返回一个io.Reader,对r中的十六进制字符进行解码。NewDecoder希望r中只包含偶数的十六进制字符。
func NewEncoder <- go1.10
|
|
NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
NewEncoder返回一个io.Writer,将小写的十六进制字符写入w中。
类型
type InvalidByteError
|
|
InvalidByteError values describe errors resulting from an invalid byte in a hex string.
InvalidByteError值描述由十六进制字符串中的无效字节导致的错误。
(InvalidByteError) Error
|
|
2.7.10 - json
json
https://pkg.go.dev/encoding/json@go1.20.1
json包实现了RFC 7159中定义的JSON编解码。JSON和Go值之间的映射在Marshal和Unmarshal函数的文档中有描述。
有关此包的介绍,请参见JSON和Go。
Example (CustomMarshalJSON)
|
|
Example(TextMarshalJSON)
|
|
常量
This section is empty.
变量
This section is empty.
函数
func Compact
|
|
Compact函数将JSON编码的src附加到dst中,省略了不重要的空格字符。
func HTMLEscape
|
|
HTMLEscape函数将JSON编码的src附加到dst中,将字符串文字内的<、>、&、U+2028和U+2029字符更改为\u003c、\u003e、\u0026、\u2028、\u2029,以使JSON可以安全地嵌入HTML <script>标记中。由于历史原因,Web浏览器不支持在<script>标记中使用标准的HTML转义,因此必须使用替代的JSON编码。
HTMLEscape Example
|
|
func Indent
|
|
Indent函数将JSON编码的src的缩进形式附加到dst中。JSON对象或数组中的每个元素都在新的缩进行上开始,该行以prefix开头,后跟一个或多个indent的副本,具体取决于缩进嵌套。附加到dst的数据不以prefix或任何缩进开始,以使其更容易嵌入其他格式化的JSON数据中。虽然src开头的前导空格字符(空格、制表符、回车、换行符)会被删除,但src末尾的尾随空格字符会被保留并复制到dst中。例如,如果src没有尾随空格,则dst也没有;如果src以尾随换行符结束,则dst也是如此。
Example
|
|
func Marshal
|
|
Marshal函数返回v的JSON编码。
Marshal函数递归遍历值v。如果遇到的值实现了Marshaler接口并且不是nil指针,则Marshal调用其MarshalJSON方法以生成JSON。如果没有MarshalJSON方法但该值代替实现了encoding.TextMarshaler,则Marshal调用其MarshalText方法并将结果编码为JSON字符串。nil指针异常并不是严格必要的,但模仿了在UnmarshalJSON的行为中必要的类似异常。
否则,Marshal使用以下类型相关的默认编码:
布尔值被编码为JSON布尔值。
浮点数、整数和Number类型的值被编码为JSON数字。
字符串类型的值被编码为JSON字符串,被强制转换为有效的UTF-8编码,无效的字节会被替换为Unicode替换符。为了将JSON安全地嵌入到HTML的